microsoft / microsoft/TypeScript
Branded literal type widened in unexpected way
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
literal intersection branded string
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about branded strings/literal intersections.
⏯ Playground Link
💻 Code
declare const typeKey: unique symbol;
type TypeID<Type = unknown, ID extends string = string> = ID & { [typeKey]?: Type };
function typeID<Type, ID extends string>(id: ID): TypeID<Type, ID> {
return id;
}
type KeyOf<TID extends TypeID> = TID extends TypeID<any, infer ID> ? ID : never;
type TypeOf<TID extends TypeID> = TID extends TypeID<infer Type> ? Type : never;
type Provides<P extends TypeID> = { readonly [T in KeyOf<P>]: TypeOf<P> };
// ---cut---
interface Foo {
foo(): void;
}
const Foo = typeID("Foo") satisfies TypeID<Foo>;
// ^? const Foo: TypeID<Foo, "Foo">
const Bar: Provides<typeof Foo> = {
[Foo]: {
foo() {}
}
};
🙁 Actual behavior
Fails to compile with error:
Property 'Foo' is missing in type '{ [x: string]: { foo(): void; }; }' but required in type 'Provides<TypeID<Foo, "Foo">>'.
🙂 Expected behavior
I'd expect it to compile. Rather than widening the literal type to string, I'd expect it to discard the { [typeKey]?: Type } part, since that's pretty much bogus at runtime anyway.
However, it should also not lose the type information for the generic types. For instance, if I change the declaration to...
type TypeID<Type = unknown, ID extends string = string> = ID;
...then it does compile, but so does this...
const Bar: Provides<typeof Foo> = {
[Foo]: {
// No error about missing member `foo` here!
}
};
Additional information about the issue
Possibly related to https://github.com/microsoft/TypeScript/issues/43852#issuecomment-1671115898
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 Reproduktion im TypeScript Playground und vergleiche das Verhalten von Branded-Literalen mit der verwandten Diskussion in Issue #43852. Verfolge den Typprüfpfad für die Definitionen TypeID, KeyOf, TypeOf und Provides; als erledigt gilt die Aufgabe, wenn das Beispiel kompiliert und weiterhin ein fehlendes foo-Member meldet, sofern dies angemessen ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- compilers, devtools
- Issue-Typ
- Bug
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100