The “is” type guard in TypeScript

The is keyword can be used to narrow types in TypeScript. What this means is that, for example if we’re testing whether an any parameter is a string a number or whatever, TypeScript will see the type as that type in subsequent code.

For example if we have the following functions

function isString(test: any): test is string {
  return typeof test === "string";
}

function isNumber(test: any): test is number {
  return typeof test === "number";
}

Each function simply takes a parameter of type any then if the return is true the parameter in subsequent code is seen by TypeScript as that type, i.e. Let’s assuming we have a some function which happens to use these functions, like this

function run(a: any) {
  if(isString(a)) {
    console.log(a)
  }
  if(isNumber(a)) {
    console.log(a)
  }
}

If you’re using Visual Code (for example) the TypeScript type popup (display when you move the mouse over the parameter a will show the type to be any in the run parameter list, or in any of the isXXX function parameters. But in the console.log after each isXXX function, TypeScript will interpret the type to be a string (in the case of isString) and a number (in the case if isNumber) hence using intellisense on the variables will list the methods etc. for a string and those for a number respectively

So basically the is keyword will appear to convert the parameter to the specified type if the function returns true.

To look at it another way we could instead write something like this

function isString(test: any): boolean {
    return typeof test === "string";
}

function isNumber(test: any): boolean {
    return typeof test === "number";
}

function run(a: any) {
  if(isString(a)) {
    const b = a as string;
    console.log(b)
  }
  if(isNumber(a)) {
    const b = a as string;
    console.log(b)
  }
}

For completeness, here’s the function syntax for a const style function

const isString = (test: any): test is string => {
  return typeof test === "string";
}