typescriptcasting

Can I do a type assertion for a variable in Typescript that should be valid for a whole block/function?


I have a state variable that is of type null | SOME_TYPE. But some functions expect it to be SOME_TYPE and those functions are 100% sure that the state variable will be SOME_TYPE when they run.

Can I type cast/assert a variable that will be valid for a whole function scope?

Example:

const [myState,setMyState] = useState<null | SOME_TYPE>(null);

function doSomething() {
  // THIS FUNCTION NEEDS myState TO BE SOME_TYPE
  // IT'S 100% GUARANTEED THAT WHEN IT RUNS, myState WILL BE SOME_TYPE

  // IT WILL ACCESS MULTIPLE PROPERTIES OF MY STATE
  console.log(myState.someProp as SOME_TYPE);
  console.log(myState.someOther as SOME_TYPE);
  console.log(myState.another as SOME_TYPE);
}

Instead of multiple and repetitive type casts, can I do a "block" type assertion (without creating a new variable)?

Example:

function doSomething() {

  // myState as SOME_TYPE
  // THE IDEA IS THAT INSIDE THIS WHOLE BLOCK myState IS CONSIDERED TO BE SOME_TYPE

  console.log(myState.someProp);
  console.log(myState.someOther);
  console.log(myState.another);
}

Is there a syntax or a proposal for that?


Solution

  • I believe that new variable is acceptable solution, but your other option is an user-defined type guard.

    Contrary to new variable with cast, the preconditon will be checked in runtime.

    function isSomeType(x: null | SOME_TYPE): x is SOME_TYPE {
      return x !== null;
    } 
    
    function doSomething() {
      if (isSomeType(myState)) {
        console.log(myState.stateSomeType);
        console.log(myState.someOther);
        console.log(myState.another);
      }
    }
    

    Also, as your type is SOME_TYPE | null, not null guard will work as well:

    function doSomething() {
      if (myState !== null) {
        console.log(myState.stateSomeType);
        console.log(myState.someOther);
        console.log(myState.another);
      }
    }
    

    Playground link