Skip to content

Inside a generic function with a remapped type as parameter, elements are wrongfully inferred as {}.Β #63363

@denis-migdal

Description

@denis-migdal

πŸ”Ž Search Terms

remapped
key mapping
generics

Maybe related:

πŸ•— Version & Regression Information

  • tested on playground v6.0.2

⏯ Playground Link

Playground Link

πŸ’» Code

    type RenameKeys<H extends Record<string, any>> = {
        [K in string&keyof H as `on${Capitalize<K>}`]: () => void
    };

    function foo<T extends Record<string, any>>(handlers: RenameKeys<T>) {

        for(const name in handlers) {
            let handler: () => void = handlers[name]!; // nok
            // inferred as {}Β instead of () => void;
            // Type 'NonNullable<RenameKeys<T>[Extract<keyof RenameKeys<T>, string>]>' is not assignable to type '() => void'.
           // Type '{}' provides no match for the signature '(): void'.(2322)
        }
   }

πŸ™ Actual behavior

The type of the elements of the remapped type is {} inside the generic function.

If we return the element, the returned type is correct (cf playground).

πŸ™‚ Expected behavior

The type should be either:

  • () = void (correct)
  • unknown or any: TS is unable to properly infer the type.

Having {} is quite strange/surprising.

Additional information about the issue

There is another issue with [K in string&keyof H] which doesn't manifest when we use [K in keyof H] (cf playground):

type RenameKeys<H extends Record<string, any[]>> = {
     [K in string&keyof H]: (...args: H[K]) => void
};

function foo<T extends Record<string, any>>(handlers: RenameKeys<T>) {

        for(const name in handlers)
            return handlers[name]!;

        throw new Error("ok");
}

const x = foo({onFoo: (e: 42) => {}}); // nok : (...args: unknown) => void

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions