microsoft / microsoft/TypeScript
Type Inference Fails with Generic Types
Personne n'a encore pris cette issue.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.4k
- Merge moyen
- 1 j 19 h
- PR mergées (30 j)
- 117
Description
🔎 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
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par le TypeScript Playground associé et réduisez l’exemple générique récursif impliquant BaseItem, Snapshot, Get et FlatQuery, en le comparant à l’affectation non générique. C’est terminé lorsque l’affectation générique { collectionName: 'asdf' } est acceptée sans affaiblir le comportement attendu signalé.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- typescript
- Domaine
- compilers
- Type d'issue
- Bug
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- Clairement spécifiée
- Accessibilité débutants
- 30/100