Nov 26, 2018
Using Typescript Type Guard to Narrow Down Type
Typescript is aware of usage of the Javascript instanceof
and typeof
operators, and will narrow down the type accordingly when you use those operators in conditional block.
ts
functiondoSomething (x : number | string) {if (typeofx === 'string') {// Within the block TypeScript knows that `x` must be a stringconsole .log (x .substr (1));}Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.2339Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.x .(1); substr }
ts
functiondoSomething (x : number | string) {if (typeofx === 'string') {// Within the block TypeScript knows that `x` must be a stringconsole .log (x .substr (1));}Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.2339Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.x .(1); substr }
(Example stolen from Typescript Deep Dive)
Usually, those typechecking are used frequently, and you may want to create some utility function to abstract it away. However, with those abstraction, you lose the narrowing down of typescript.
ts
functionisString (value : any) {return typeofvalue === 'string';}functiondoSomething (x : number | string) {if (isString (x )) {// Typescript doesn't know that x must be a stringProperty 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.2339Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.console .log (x .(1)); // Error substr }}
ts
functionisString (value : any) {return typeofvalue === 'string';}functiondoSomething (x : number | string) {if (isString (x )) {// Typescript doesn't know that x must be a stringProperty 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.2339Property 'substr' does not exist on type 'string | number'. Property 'substr' does not exist on type 'number'.console .log (x .(1)); // Error substr }}
Solution: Custom Type Guard
Typescript introduces the concept of custom type guard, which allows you to create utility function that assert the type of the parameters.
ts
functionisString (value : any):value is string {return typeofvalue === 'string';}functiondoSomething (x : number | string) {if (isString (x )) {console .log (x .substr (1)); // OK}}
ts
functionisString (value : any):value is string {return typeofvalue === 'string';}functiondoSomething (x : number | string) {if (isString (x )) {console .log (x .substr (1)); // OK}}
Side Note: npm package for common type checking
I’ve published a npm package, typesafe-is
that consists of common type-checking with typeguard, as those are required in almost are javascript applications.