如何为嵌套NoSQL集合自动推断Collection类的TypeScript类型?
解决方案:自动推断嵌套NoSQL集合的TypeScript类型
要实现从构造函数参数自动推断ID键名、父集合类型,仅需手动指定自定义Id<>类型,无需额外传递其他泛型参数,可以通过调整泛型约束和构造函数的类型推断逻辑实现。以下是完整的类型定义:
declare const t: unique symbol; export type Id<T> = string & { readonly [t]: T }; // 递归提取集合及其所有父集合的ID键值对类型 type DocumentIds<C> = C extends Collection<infer IdType, infer ParentCollection, infer IdKey> ? { [K in IdKey]: IdType } & (ParentCollection extends void ? {} : DocumentIds<ParentCollection>) : never; // 调整泛型顺序,让TypeScript自动推断IdKey和父集合类型 class Collection< IdType extends string = string, PC extends Collection | void = void, IdKey extends string = string > { constructor( private readonly collectionName: string, private readonly idName: IdKey, private readonly parent?: PC ) {} getCollectionPath( ids: PC extends void ? void : DocumentIds<PC> ): string {} getDocumentPath( ids: DocumentIds<this> ): string {} parse(path: string): DocumentIds<this> { return null as any; } } // 自定义ID类型 type AccountId = Id<'Account'>; type UserId = Id<'User'>; // 根集合:仅需指定IdType,其余类型自动推断 const AccountCollection = new Collection<AccountId>('accounts', 'accountId'); // 子集合:仅需指定IdType,父集合类型和ID键名自动推断 const UserCollection = new Collection<UserId>('users', 'userId', AccountCollection); // 测试用例 // 根集合获取集合路径,无需参数 AccountCollection.getCollectionPath(); // 返回 'accounts' // 根集合获取文档路径,需传入accountId AccountCollection.getDocumentPath({ accountId: 'acc-1' as AccountId, }); // 返回 'accounts/acc-1' // 子集合获取集合路径,需传入父集合的accountId UserCollection.getCollectionPath({ accountId: 'acc-1' as AccountId, }); // 返回 'accounts/acc-1/users' // 子集合获取文档路径,需传入父集合ID和自身ID UserCollection.getDocumentPath({ accountId: 'acc-1' as AccountId, userId: 'usr-1' as UserId, }); // 返回 'accounts/acc-1/users/usr-1' // 解析路径返回强类型的ID键值对 const ids = UserCollection.parse('accounts/acc-1/users/usr-1'); // ids类型为 { accountId: AccountId; userId: UserId }
核心优化说明
- 自动泛型推断:构造函数的
idName参数会自动映射到IdKey泛型,parent参数会自动映射到PC泛型,因此创建集合实例时仅需手动指定自定义的Id<>类型即可。 - 递归ID类型提取:
DocumentIds类型递归遍历集合的父链,自动拼接所有层级的ID键值对类型,避免手动维护嵌套类型。 - 简化方法类型:使用
DocumentIds<this>统一方法的参数和返回类型,保证类型一致性的同时简化代码结构。
内容的提问来源于stack exchange,提问作者Dominic
相关产品推荐
相关产品推荐

