้•œๅƒ็ซ™็‚น ยท ๆœฌ้กต็”ฑ็ฌฌไธ‰ๆ–น GitHub ๅช่ฏป้•œๅƒๆไพ›๏ผŒ้ž GitHub ๅฎ˜ๆ–น็ซ™็‚น๏ผŒไธๆŽฅๅ—ไปปไฝ•็™ปๅฝ•ๆˆ–ๅ‡ญๆฎ่พ“ๅ…ฅใ€‚ๅ‰ๅพ€ github.com
Skip to content

Generics get broken when inferred from a function with an implicitly typed parameterย #54438

Description

Bug Report

๐Ÿ”Ž Search Terms

generic, function, parameters, unknown, never

๐Ÿ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about Generics

โฏ Playground Link

Playground link with relevant code

๐Ÿ’ป Code

interface Entity {
    id: number;
    name: string;
}

type Fn<T> = (params: Record<string, unknown>) => T[];

declare function test<T, K extends keyof T>(fn: Fn<T>, key: K): T;

// Case #1: params aren't used, generic is `<Entity, 'id'>` โœ…
test(() => [] as Entity[], 'id');

// Case #2: params are used with a type being explicitly specified, generic is `<Entity, 'name'>` โœ…
test((params: Record<string, unknown>) => [] as Entity[], 'name');

// Case #3: params are used with a different type, generic is `<Entity, 'id'>` โœ…
test((params: unknown) => [] as Entity[], 'id');

// Case #4: params are used with an implicit type, generic is <unknown, never> โŒ
test((params) => [] as Entity[], 'id');
      ^ but it's inferred properly as Record<string, unknown>

๐Ÿ™ Actual behavior

In the case 4 a generic gets broken and has a type <unknown, never> instead of <Entity, 'id'> as shown in the previous examples.
There's nothing wrong with an implicit type for params since it's already automatically inferred as Record<string, unknown>.

๐Ÿ™‚ Expected behavior

The case 4 should work exactly the same as the previous ones and missing type annotation in parameters should have no impact on the inferred generic type.

Activity

  1. jcalz commented on May 29, 2023

    @jcalz
    Contributor

    Duplicates the part of #47599 that's still unresolved... and might never be resolved, see #48538 (comment):

    () => 42 and (n: number) => n are context insensitive because they have no contextually typed parameters, but n => n and function() { return 42 } are context sensitive because they have at least one contextually typed parameter (in the function expression case, the implicit this parameter is contextually typed). The errors in the last two calls occur because inferred type information only flows from left to right between context sensitive arguments. This is a long standing limitation of our inference algorithm, and one that isn't likely to change. [emphasis added]

  2. fatcerberus commented on May 29, 2023

    @fatcerberus

    Thanks Joe Calzaretta (@jcalz), I suspected this was related to contextual typing but wasn't confident enough about the cause to jump in. I thought it might just be a circularity (i.e. T infers from function parameter -> arrow function is contextually typed by T -> cycle detected -> default to constraint)

  3. mattersj commented on May 31, 2023

    @mattersj
    Author

    Joe Calzaretta (@jcalz) Thank you for clearing this up, it makes sense now. I'm going to close this one as it already has a bunch of duplicates out there.
    So, for anyone coming up here the best solution is to explicitly add a type annotation for your parameter like this: (params: YourType) => ... or get rid of your parameter at all.

  4. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions