TypeScript Version: 2.2.1
Code
(async () => {
function foo(p: string[]): string[] {
return [];
}
function bar(p: string[]): string[] {
return [];
}
let a1: string[] | undefined = [];
while (true) {
let a2 = foo(a1!);
a1 = await bar(a2);
}
});
With noImplicitAny and strictNullChecks turned on, this gives error:
'a2' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
When inferring the type of a variable from its initializer we're performing a full type check of the initializer instead of just doing the minimal work to obtain its type (i.e. we're using checkExpression instead of getTypeOfExpression). This full type check causes a circularity to surface. We just need to be a little less eager.
A possibly related case:
type AB = A | B;
class A { _a: any; }
class B { _b: any; }
declare function create<T>(b: boolean): T;
function f() {
let ab: AB = new B();
while (true) {
const b = create<B>(ab !== undefined);
ab = b;
}
}
src/a.ts(10,15): error TS7022: 'b' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
Most helpful comment
When inferring the type of a variable from its initializer we're performing a full type check of the initializer instead of just doing the minimal work to obtain its type (i.e. we're using
checkExpressioninstead ofgetTypeOfExpression). This full type check causes a circularity to surface. We just need to be a little less eager.