Reputation: 6297
In the below example:
type Foo = () => void;
let a: Foo | undefined = undefined;
const c = () => { a = () => console.log("Hi!") };
c();
if (a) {
a();
}
At line 4 the type of a
is let a: Foo | undefined
but at line 8 it is let a: never
.
Therefore tsc
shows this error: Type 'never' has no call signatures
at line 8.
But it doesn't if line 2 is let a: Foo | undefined;
(removed the variable assignment)
I guess it will be something related with Type Inference. The docs states that:
In TypeScript, there are several places where type inference is used to provide type information when there is no explicit type annotation.
let x = 3; ^ let x: number
But I this example there is an explicit type annotation.
I understand that TS cannot know if the function c
will be executed and, therefore, that a
will be assigned. That is why I have put the explicit definition of the type of a
in its declaration.
So why is the type defined for a
not respected at line 8?
Upvotes: 3
Views: 131
Reputation: 51132
This is unsound behaviour, as you note in your question. The behaviour is noted in an open issue on the GitHub issue tracker, titled Trade-offs in Control Flow Analysis:
Optimistic: Bad behavior on locals
The TypeScript compiler has code like this:
enum Token { Alpha, Beta, Gamma } let token = Token.Alpha; function nextToken() { token = Token.Beta; } function maybeNextToken() { if (... something ...) { nextToken(); } } function doSomething() { if (token !== Token.Alpha) { maybeNextToken(); } // is this possible? if (token === Token.Alpha) { // something happens } }
Optimistically assuming
token
isn't modified bymaybeNextToken
incorrectly flagstoken === Token.Alpha
as an impossibility. However, in other cases, this is a good check to do! See later examples.
The problem is that making the compiler more pessimistic would be detrimental in other cases, because the compiler would fail to detect real bugs in your code. As of writing this answer, the issue is over 5 years old and still open, and it looks like the language designers haven't agreed on whether anything needs to be done about it, or if so what.
Upvotes: 1