microsoft / microsoft/TypeScript
Inside a generic function with a remapped type as parameter, elements are wrongfully inferred as {}.
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Go
- Sterne
- 111k
- Forks
- 14.3k
- Ø Merge
- 2 T. 4 Std.
- Gemergte PRs (30 T.)
- 132
Beschreibung
🔎 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
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit der verlinkten Playground-Reproduktion und vergleiche den remappten Typ mit string & keyof H mit der Variante keyof H. Verfolge, wie der Elementzugriff innerhalb der generischen Funktion foo inferiert wird. Als abgeschlossen gilt die Arbeit, wenn das remappte Handler-Element als () => void oder als unknown oder any statt als {} inferiert wird und die gemeldeten Fälle abgedeckt sind.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- compilers
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 45/100