microsoft / microsoft/TypeScript
Type inference only works on the same line as the variable declaration
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
I ran into this odd behavior while writing some tests, that do the typical describe, declare a closure-scope variable, and in beforeEach, assign some object to that variable that is used in each of the tests inside.
Search Terms:
infer, inference, closure, scope, broken, any, cast
Initially, I thought it was limited to closure scope, but I then started reducing the reproduction sample more and more, and realized, it's broken even if it's on the very next line:
Code
// given
interface Foo {
id: string;
}
function make(): Foo {
return {
id: 'akatechis',
}
}
// u1 is correctly inferred to be of type Foo.
let u1 = make();
// u2 is incorrectly inferred to be of type any.
let u2;
u2 = make();
// this was the scenario in which I originally ran into this:
// a closure scoped variable that is assigned in an inner function
function outer () {
// u3 is inferred to be of type any
let u3;
return {
inner() {
// u3 here is still any
u3 = make();
// surprisingly, returning u3 here causes the return type of inner() to be Foo, not any???
return u3;
}
}
}
Expected type declarations:
interface Foo {
id: string;
}
declare function make(): Foo;
declare let u1: Foo;
declare let u2: Foo; // <---- this should have been inferred to be Foo
declare function outer(): {
inner(): Foo;
};
Actual type declarations:
interface Foo {
id: string;
}
declare function make(): Foo;
declare let u1: Foo;
declare let u2: any;
declare function outer(): {
inner(): Foo;
};
Playground Link: playground
Related Issues:
The only thing that I found somewhat close to this issue was the question in the FAQ about unused generic types causing type widening, but I don't think this is it, because I'm not using generics here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground reproduction and compare the inferred declarations for u1, u2, and outer(). Read the related FAQ entry about type widening to rule out that explanation, then identify the type-inference behavior responsible for the mismatch. Done means u2 is inferred as Foo while preserving the shown outer() result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100