Closed
Description
TypeScript Version: 2.7.1
Search Terms: infer
Code
interface IFooOptions<K extends string> {
name?: string;
value?: number;
allFoos?: {[key in K]?: boolean }
fn?: (allFoos: {[key in K]: string }) => void;
}
class Bar<T> {
constructor(foos: {[key in keyof T]: IFooOptions<keyof T> }) {
// ...
}
}
const bar = new Bar({
firstFoo: {
name: "john",
value: 3,
allFoos: { // here allFoos infered
firstFoo: true,
nonexist: 'yep'
}
},
secondFoo: {
name: 'sandra',
fn: allFoos => { // but here allFoos is any though the type of "fn" is infered correctly
allFoos.nonexist = 2
}
}
});
const myFoo: IFooOptions<'one' | 'two'> = {
name: 'adas',
fn: allFoos => { //allFoos is infered right
allFoos.nonexist = 2
}
}
Expected behavior:
The allFoos
argument inside fn
field in the new Bar
argument should have a type of
{
firstFoo: string
secondFoo: string
}
Actual behavior:
allFoos
type is implicit any
Also it repoduces without using a class, just with plain generic function
Activity
RyanCavanaugh commentedon Mar 20, 2018
@sandersn is this a duplicate of #22362 ?
ghost commentedon Mar 22, 2018
This looks like a separate bug. The type parameter is escaping!
@beshanoe To fix the issue for now you should provide an explicit type argument. I'm don't think we should be able to infer
T
if we only ever see its keys anyway. At the comment at// here allFoos infered
, there actually was no type argument inference, but if you hover over it you will still see a type -- that is just telling you the type of that object literal.beshanoe commentedon Mar 22, 2018
@Andy-MS regarding argument, I was saying about this place:
if you remove error line "nonexistent": "yep", you will see that fn's type is inferred when I hover it, however allFoos argument is any

ghost commentedon Mar 22, 2018
I was confused by not getting errors (#22790). Now that I look at the original example again, there is a type error at
nonexist: 'yep'
, so this may not actually be a bug.beshanoe commentedon Apr 16, 2018
@Andy-MS could you please explain your latest statement? Is it a bug? To me it looks like it is :)
I've encountered the same thing again, and it really prevents me from doing good typing in my app.
It's reproduced in 2.8.1 version
Here's is another example:
https://www.typescriptlang.org/play/index.html#src=class%20RouterProps%3CP%3E%20%7B%0D%0A%20%20props%3A%20P%0D%0A%7D%0D%0A%0D%0Aclass%20Component%3CP%3E%20%7B%0D%0A%20%20props%3A%20P%0D%0A%7D%0D%0A%0D%0A%2F%2F%20in%20'resolve'%20field%20I%20want%20to%20pass%20an%20object%20with%20keys%20from%20passed%20component's%20props%20and%20with%20functions%20as%20values%0D%0Ainterface%20IRoute%3CP%20%3D%20any%2C%20RP%20%3D%20any%3E%20%7B%0D%0A%20%20name%3A%20string%0D%0A%20%20component%3A%20Component%3CP%20%26%20RouterProps%3CRP%3E%3E%2C%0D%0A%20%20resolve%3F%3A%20%7B%20%5Bname%20in%20keyof%20P%5D%3F%3A%20(params%3A%20RP)%20%3D%3E%20Promise%3CP%5Bname%5D%3E%20%7D%0D%0A%7D%0D%0A%0D%0Afunction%20route%3CP%2C%20RP%3E(route%3A%20IRoute%3CP%2C%20RP%3E)%20%7B%0D%0A%20%20return%20route%0D%0A%7D%0D%0A%0D%0Aconst%20cmp%20%3D%20new%20Component%3C%7B%20foo%3A%20number%2C%20bar%3A%20string%20%7D%20%26%20RouterProps%3C%7B%20id%3A%20string%20%7D%3E%3E()%0D%0A%0D%0A%0D%0A%2F%2F%20if%20you%20hover%20'resolve'%20or%20'foo'%20object's%20field%2C%20the%20type%20is%20inferred%20correctly%2C%20saying%20that%20'params'%20arg%20is%20of%20type%20%7Bid%3A%20string%7D%0D%0A%2F%2F%20but%20when%20you%20hover%20'params'%2C%20it%20says%20that%20it's%20'any'%0D%0Aroute(%7B%0D%0A%20%20name%3A%20'sample-route'%2C%0D%0A%20%20component%3A%20cmp%2C%0D%0A%20%20resolve%3A%20%7B%0D%0A%20%20%20%20foo%3A%20params%20%3D%3E%20%7B%0D%0A%20%20%20%20%20%20alert(params.nonexistent)%20%2F%2F%20no%20error%20here%2C%20but%20should%20be%0D%0A%20%20%20%20%20%20return%20Promise.resolve(10)%20%2F%2F%20notice%20that%20the%20type%20of%20return%20value%20is%20enforced%2C%20namely%20change%2010%20to%20%22somestring%22%20and%20there%20will%20be%20an%20error%0D%0A%20%20%20%20%7D%0D%0A%20%20%7D%0D%0A%7D)
ghost commentedon Apr 16, 2018
@beshanoe Try turning on
--noImplicitAny
-- no type was inferred forparams
. It looks like you need to explicitly provide type arguments toroute
. However, I did file an issue based on this at #23429.beshanoe commentedon Apr 16, 2018
@Andy-MS cool thanks, do you think this issue is a "good first issue"? Or it's too complicated? I just want to try to start contributing to TS :)
ghost commentedon Apr 16, 2018
That seems like a pretty tough issue to me, since it involves type inference, and contextual typing of lambdas, and mapped types, all together.
RyanCavanaugh commentedon Sep 16, 2019
This has been fixed (verified in 3.6)