Skip to content

Inconsistent behavior when inferring a generic type from a functionΒ #52580

Closed
@greim

Description

@greim

Bug Report

πŸ”Ž Search Terms

Not sure what to search for, tried various combos of "infer" "generic" "function" but seems too general.

πŸ•— Version & Regression Information

Tried in 4.0.5, 4.6.3, and 4.9.4.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

// see also playground link

type Funcs<A, B extends Record<string, unknown>> = {
  [k in keyof B]: {
    fn: (a: A, b: B) => void;
    thing: B[k];
  };
}

function foo<A, B extends Record<string, unknown>>(fns: Funcs<A, B>) {}

foo({
  bar: {
    fn: (a: string) => {}, // <-- ERROR HERE
    thing: 'asd',
  },
});

foo({
  bar: {
    fn: (a: string, b) => {}, // <-- NO ERROR HERE
    thing: 'asd',
  },
});

Actual behavior

It infers generic <A> as unknown, in the former case only. It then checks assignability of unknown to a: string and raises an error.

Type '(a: string) => void' is not assignable to type '(a: unknown, b: { bar: string; }) => void'.
  Types of parameters 'a' and 'a' are incompatible.
    Type 'unknown' is not assignable to type 'string'.(2322)
input.tsx(3, 5): The expected type comes from property 'fn' which is declared here on type '{ fn: (a: unknown, b: { bar: string; }) => void; thing: string; }'

Expected behavior

I didn't expect it to infer unknown in the former case, and more generally was surprised that including/excluding b from the argument list would affect inference from a. I thought it should see string in both cases, and that all of the above would compile.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions