microsoft / microsoft/TypeScript
Type Inference Fails with Generic Types
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Go
- Sterne
- 111k
- Forks
- 14.3k
- Ø Merge
- 1 T. 19 Std.
- Gemergte PRs (30 T.)
- 117
Beschreibung
🔎 Search Terms
error recursive generic types
🕗 Version & Regression Information
- This changed between versions v5.7.0-beta and v4.1.5
⏯ Playground Link
💻 Code
type BaseItem<T = any> = { id: T }
interface Snapshot<T extends BaseItem<I> = BaseItem, I = any> {
id: string,
time: number,
collectionName: string,
items: T[],
}
const selector: FlatQuery<Snapshot<BaseItem>> = { collectionName: 'asdf' }
// ^^
// No error ✅
function test<ItemType extends BaseItem<IdType>, IdType = any>() {
type ItemKeys = DotNotationKeys<Snapshot<ItemType, IdType>>
// ^^
// "id" | "time" | "collectionName" | "items" | `items.${string}`
type CollectionNameType = Flatten<Get<Snapshot<ItemType, IdType>, 'collectionName'>>
// ^^
// "string"
const genericSelector: FlatQuery<Snapshot<ItemType, IdType>> = { collectionName: 'asdf' }
// ^^
// Error ❌: Type '{ collectionName: string; }' is not assignable to type 'FlatQuery<Snapshot<ItemType, IdType>>'.
}
// Utility type to check if a type is an array or object.
type IsObject<T> = T extends object ? (T extends Array<any> ? false : true) : false
// Recursive type to generate dot-notation keys
type DotNotationKeys<T> = {
[K in keyof T & (string | number)]:
T[K] extends Array<infer U>
// If it's an array, include both the index and the $ wildcard
? `${K}` | `${K}.$` | `${K}.${DotNotationKeys<U>}`
// If it's an object, recurse into it
: IsObject<T[K]> extends true
? `${K}` | `${K}.${DotNotationKeys<T[K]>}`
: `${K}` // Base case: Just return the key
}[keyof T & (string | number)]
type Split<S extends string, Delimiter extends string> =
S extends `${infer Head}${Delimiter}${infer Tail}`
? [Head, ...Split<Tail, Delimiter>]
: [S]
type GetTypeByParts<T, Parts extends readonly string[]> =
Parts extends [infer Head, ...infer Tail]
? Head extends keyof T
? GetTypeByParts<T[Head], Extract<Tail, string[]>>
: Head extends '$'
? T extends Array<infer U>
? GetTypeByParts<U, Extract<Tail, string[]>>
: never
: never
: T
type Get<T, Path extends string> =
GetTypeByParts<T, Split<Path, '.'>>
type Flatten<T> = T extends any[] ? T[0] : T
type FlatQuery<T> = {
[P in DotNotationKeys<T>]?: Flatten<Get<T, P>>
}
🙁 Actual behavior
Typescript isn't able to assign { collectionName: 'asdf' } when using generic types:
function test<ItemType extends BaseItem<IdType>, IdType = any>() {
const selector: FlatQuery<Snapshot<ItemType, IdType>> = { collectionName: 'asdf' }
// ^^
// Type '{ collectionName: string; }' is not assignable to type 'FlatQuery<Snapshot<ItemType, IdType>>'.
}
Without generic types it work seamlessly:
const selector: FlatQuery<Snapshot<BaseItem>> = { collectionName: 'asdf' }
🙂 Expected behavior
{ collectionName: 'asdf' } should be successfully assignable to FlatQuery<Snapshot<ItemType, IdType>> using generic types.
Additional information about the issue
Related issue: https://github.com/maxnowack/signaldb/pull/1030
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 dem verlinkten TypeScript Playground und reduziere das rekursive generische Beispiel mit BaseItem, Snapshot, Get und FlatQuery, wobei du es mit der nicht-generischen Zuweisung vergleichst. Als erledigt gilt, dass die generische { collectionName: 'asdf' }-Zuweisung akzeptiert wird, ohne das erwartete gemeldete Verhalten abzuschwächen.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- typescript
- Bereich
- compilers
- Issue-Typ
- Bug
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 30/100