Class property type inference failure when destructuring return value of generic function
See original GitHub issueBug Report
🔎 Search Terms
Class Property Destructuring Type Inference Generic
🕗 Version & Regression Information
- This is a crash: No
- The issue occurs on the latest nightly (v4.9.0-dev.20221017), as well as on version 4.7.4. I haven’t tested on other versions, but my suspicion is that this has been a hidden bug for a while.
⏯ Playground Link
Playground link with relevant code
💻 Code
class Foo {
constructor() {
[this.x, this.y] = init();
}
x; // Any
y; // Any
}
function init<T>() {
return [0, ""] as [number, string];
}
🙁 Actual behavior
The x
and y
properties are typed as any
.
🙂 Expected behavior
The x
and y
properties should be typed as number
and string
respectively.
Further investigation
If the return value of the function is captured in a local variable, and then destructured from there, everything works as expected:
class Foo {
constructor() {
const bar = init();
[this.x, this.y] = bar;
}
x; // number
y; // string
}
function init<T>() {
return [0, ""] as [number, string];
}
Or, if the generic argument is omitted, everything works as expected:
class Foo {
constructor() {
[this.x, this.y] = init();
}
x; // number
y; // string
}
function init() {
return [0, ""] as [number, string];
}
Making use the generic type argument T
does not appear to resolve the issue:
class Foo {
constructor() {
[this.x, this.y] = init(false);
}
x; // Any, should be number
y; // Any, should be boolean
}
function init<T>(value: T) {
return [0, value] as [number, T];
}
Issue Analytics
- State:
- Created a year ago
- Comments:8 (1 by maintainers)
Top Results From Across the Web
Meta-issue: Use Full Unification for Generic Inference? #30134
Function type argument inference indirectly lost with generic function #29900 ... Class property type inference failure when destructuring return value of ...
Read more >How to resolve generic type of property value from decorated ...
The decorator is basically a curried function f(x)(y) , and to fix this the compiler would have to infer the type of f...
Read more >Documentation - More on Functions - TypeScript
Functions are the basic building block of any application, whether they're local functions, imported from another module, or methods on a class.
Read more >Deconstructing tuples and other types | Microsoft Learn
The following example uses type inference when deconstructing the three-tuple returned by the QueryCityData method.
Read more >Type Inference - TypeScript Deep Dive - Gitbook
This is an example of types flowing from left to right. The same assignment style type inference works if you create a function...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
As an additional note: If you’re wondering why the compiler thinks
T
might depend on the type ofx
andy
, it’s due to the same contextual typing mechanism that makes this work:For context:
Looks like a design limitation. Essentially
x
andy
become part of the context for the generic call: TS wants to knowT
, but first it needs to know what the type ofx
is (because contextual typing plays into generic inference), but for that it needs to instantiateT
, etc. That the return value is actually non-generic doesn’t matter because it doesn’t have a usable first-order function signature until it’s instantiatedinit
. So the end result is you hit a circularity and the compiler gives up.tl;dr: the type of a property is both the input and output of a generic instantiation, the compiler can’t resolve the cycle and so falls back to
any