Reputation: 1056
I feel like this should totally be possible in typescript, but it seems as if typescript doesn't properly type this. Is there any way to do this? Here's a super simple example, but I'm specifically looking to automatically infer argument types when passing a function to a react component's prop that takes a callback with a defined type
function constrainingFunction(b: number) {
return b + 1
}
function test(a) { // ERROR: `a` implicitly has an `any` type
constrainingFunction(a)
}
test(1)
function constrainingFunction(b: number) {
return b + 1
}
function test(a) { // `a` should properly be inferred as `number`
constrainingFunction(a)
}
test(1)
Upvotes: 4
Views: 3851
Reputation: 329573
See microsoft/TypeScript#34738 for a canonical answer.
TypeScript does not perform contextual typing of function parameters from usage this way, apparently for performance reasons. According to this comment by the dev lead for the TS team,
This has been an intentional design constraint since inception; not doing this is a key reason TS performance is remotely acceptable.
There's also this comment in a related issue:
People have asked us hundreds of times why we don't do this; the answer is that it's architecturally impractical to do this in a way that results in stable, performant checking results in anything other than toy programs.
So the a
parameter will need to be explicitly annotated as number
in order for this code to work as intended without error.
But you don't necessarily need to be the one annotating it yourself. As both comments above go on to say:
The "infer from usage" refactor will produce a type for you on an as-requested basis.
The "infer from usage" refactor is available for this purpose.
So TypeScript can infer the type from usage, but not automatically during compilation. You can specifically request it in an IDE that supports Code Actions like Visual Studio or The TypeScript Playground.
If you select the offending a
parameter, you should see a light bulb, which when clicked, suggests "infer parameter types from usage":
function constrainingFunction(b: number) {
return b + 1
}
// 💡 [ infer parameter types from usage ]
function test(a) { // ERROR: `a` implicitly has an `any` type
// -------> ~
constrainingFunction(a)
}
test(1)
And if you accept that suggestion, the desired explicit annotation will occur:
function constrainingFunction(b: number) { // <-- magic!
return b + 1
}
function test(a: number) {
constrainingFunction(a)
}
test(1)
Supplementary animated screenshot:
So that might be some consolation for you.
Upvotes: 5