Skip to content

Wrong type inferring invoking generic function with parameter destructing #42030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mszkudelski opened this issue Dec 18, 2020 · 1 comment · Fixed by #42038
Closed

Wrong type inferring invoking generic function with parameter destructing #42030

mszkudelski opened this issue Dec 18, 2020 · 1 comment · Fixed by #42038
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@mszkudelski
Copy link

TypeScript Version: 4.0.5

Search Terms:
generic inferring destructing function parameter

Description
I declared generic function with two generic types. One is depended on the other by keyof. Function takes one argument that is destructing and described by one interface (also generic). One of the parameters should be key of other one.
When I pass object with only these two depended properties TS throw confusing error.

After passing all properties to that object TS not complainig about this any more.
Moreover, if I change function to take seperate arguments (with the same typings) there is no such error.

Expected behavior:
Should throw error telling me that passed parameter is not assignable to interface ListProps, because it don't implement third property.
Moreover, TS is not inferring types of first two properties - I think it should.

Actual behavior:
There is confusing error after passing two of three properties with object as function argument:

Type 'string' is not assignable to type 'never'.(2322)
input.tsx(3, 3): The expected type comes from property 'itemKey' which is declared here on type 'ListProps<unknown, never>'

Related Issues:

Code

export interface ListProps<T, K extends keyof T> {
  items: T[];
  itemKey: K;
  prop: number
}


export const Component = <T, K extends keyof T>({
  items,
  itemKey,
  prop,
}: ListProps<T, K>) => {}

// throws confusing error
Component({items: [{name:' string'}], itemKey: 'name'})

// work after passing last property
Component({item: {name:' string'}, itemKey: 'name', prop: 1})

// work as expected without parameter destructing
export const Component2 = <T, K extends keyof T>(items: T[],
  itemKey: K,
  prop: number) => {}

// throws 'Expected 3 arguments, but got 2.'
Component2([{name:' string'}],  'name')
Output
export const Component = ({ items, itemKey, prop, }) => { };
Component({ items: [{ name: ' string' }], itemKey: 'name' });
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "declaration": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": 2,
    "target": "ES2017",
    "jsx": "React",
    "module": "ESNext"
  }
}

Playground Link: Provided

@ahejlsberg
Copy link
Member

You're right, there's a little quirk in type inference that causes us to sometimes not infer types for T and K in the case where a property is missing in the source. We ought to make inferences and then report a missing property error, as you suggest.

@ahejlsberg ahejlsberg added the Bug A bug in TypeScript label Dec 18, 2020
@ahejlsberg ahejlsberg added this to the TypeScript 4.2.0 milestone Dec 18, 2020
@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Dec 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants