Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript Type Guards and fat arrow function

Tags:

Shouldn't this compile correctly? I get an error "Property 'hello' does not exist on type 'object'." in the highlighted line.

I can access g.hello outside the fat arrow function without problems.

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

let g : object;

if (g instanceof Test) {
    () => {
        g.hello();    ////// ERROR HERE /////
    };
}
like image 469
Roddy Avatar asked Dec 05 '18 22:12

Roddy


People also ask

What are TypeScript type guards?

A type guard is a TypeScript technique used to get information about the type of a variable, usually within a conditional block. Type guards are regular functions that return a boolean, taking a type and telling TypeScript if it can be narrowed down to something more specific.

Does TypeScript support arrow function?

ES6 version of TypeScript provides an arrow function which is the shorthand syntax for defining the anonymous function, i.e., for function expressions. It omits the function keyword. We can call it fat arrow (because -> is a thin arrow and => is a "fat" arrow). It is also called a Lambda function.

What does fat arrow mean in TypeScript?

The fat arrow => separates the function parameters and the function body. The right side of => can contain one or more code statements. The above arrow function sum will be converted into the following JavaScript code. var sum = function (x, y) { return x + y; }

What => means in TypeScript?

In a type position, => defines a function type where the arguments are to the left of the => and the return type is on the right. So callback: (result: string) => any means " callback is a parameter whose type is a function.


1 Answers

The narrowing that a type-guard does on a variable (or anything else) will not cross fucntion boundaries. This is a design limitation.

A way to work around this issue is to assign g to a new variable, which will have it's type inferred based on the narrowing. Accessing the new variable in the arrow function will work as expected:

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

let g : object;

if (g instanceof Test) {
    const gTest = g;
    () => {
        gTest.hello();
    };
}

Another way to work around this issue if g does not change, is to declare g with const. This will let the compiler preserve the narrowing:

let g : object;

if (g instanceof Test) {
    const gTest = g;
    () => {
        gTest.hello();
    };
}

Playground Link

like image 128
Titian Cernicova-Dragomir Avatar answered Nov 15 '22 05:11

Titian Cernicova-Dragomir