microsoft / microsoft/TypeScript
Inside a generic function with a remapped type as parameter, elements are wrongfully inferred as {}.
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.3k
- Merge medio
- 2 d 4 h
- PR fusionados (30 d)
- 132
Descripción
🔎 Search Terms
remapped
key mapping
generics
Maybe related:
- https://github.com/microsoft/TypeScript/issues/47794
- https://github.com/microsoft/TypeScript/issues/48855
🕗 Version & Regression Information
- tested on playground v6.0.2
⏯ 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)unknownorany: 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
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con la reproducción enlazada en Playground y compara el tipo remapeado usando string & keyof H con la variante keyof H. Rastrea cómo se infiere el acceso a elementos dentro de la función genérica foo. Se considera terminado cuando el elemento del handler remapeado se infiere como () => void, o como unknown o any en lugar de {}, con cobertura para los casos reportados.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 45/100