从多接口类型联合中推断单个接口的TypeScript优化问询
产品许可证查询系统类型推断优化方案
问题背景
我正在开发一款产品许可证查询系统,用户可搜索旗下各产品的许可证列表,查看许可证详情及对应授权功能(不同许可证的功能存在差异)。
目前已实现一套方案:定义了包含通用信息的BaseLicense接口,以及继承该接口的SingleLicense接口;LicenseType为Lic1至Lic5的接口联合类型,当前可将Result类型传入LicenseData的泛型参数实现功能,但希望优化——根据选中单个许可证时获取的字符串变量,自动推断features属性对应的LicenseType接口。
现有实现代码
// licenses.d.ts export const product = { Lic1: "" }; type StringTupple = [string, string]; type StringNumberTupple = [string, number]; type LicenseType = Lic1 | Lic2 | Lic3 | Lic4 | Lic5; type Product = typeof product; type Result = Extract<LicenseType, { type: `${keyof Product}` }>; interface BaseLicense { Created: Date; Id: string; ProductId: number; ProductName: string; } interface SingleLicense<T> extends BaseLicense { Data: LicenseData<T>; WorkOrder: string; } interface LicenseData<T> extends SingleLicense<T> { Features: T; LicenseId: string; } interface Lic1 { readonly type: "Lic1"; Endpoints: StringTupple[]; } interface Lic2 { readonly type: "Lic2"; Ips: string; System: { Users: number, Computers: number }; } interface Lic3 { readonly type: "Lic3"; Legacy: string; LegacyMode: number; Demo: number; Filter: { Max: number, Pooling: number, Databases: number }; } interface Lic4 { readonly type: "Lic4"; State: number; Clients: number; Users: number; } interface Lic5 { readonly type: "Lic5"; Items: StringTupple[]; Values: StringTupple[]; }
优化需求
LicenseType保持联合类型不变- 能够根据选中许可证时获取的字符串变量,自动推断
features属性对应的具体Lic接口类型
优化方案
1. 修正循环引用问题
原代码中LicenseData<T>继承SingleLicense<T>,而SingleLicense<T>又包含Data: LicenseData<T>,造成类型循环引用。调整结构,让LicenseData直接继承BaseLicense:
interface SingleLicense<K extends keyof LicenseTypeMap> extends BaseLicense { Data: LicenseData<K>; WorkOrder: string; } interface LicenseData<K extends keyof LicenseTypeMap> extends BaseLicense { Features: LicenseTypeMap[K]; LicenseId: string; }
2. 创建许可证类型映射
建立字符串类型到具体许可证接口的映射,让TypeScript能通过字符串索引自动推断类型:
type LicenseTypeMap = { "Lic1": Lic1; "Lic2": Lic2; "Lic3": Lic3; "Lic4": Lic4; "Lic5": Lic5; };
3. 基于字符串变量的自动推断
通过泛型约束,接收许可证类型字符串,自动关联对应的Features类型:
// 示例函数:根据许可证类型字符串获取详情 function fetchLicenseDetails<K extends keyof LicenseTypeMap>(licenseType: K): SingleLicense<K> { // 模拟数据获取逻辑 return {} as SingleLicense<K>; } // 使用示例 const selectedType = "Lic2"; const licenseDetails = fetchLicenseDetails(selectedType); // licenseDetails.Data.Features 会自动推断为Lic2类型,可直接访问Ips、System等属性
4. 保留LicenseType联合类型
原LicenseType联合类型可继续用于需要涵盖所有许可证类型的场景:
type LicenseType = Lic1 | Lic2 | Lic3 | Lic4 | Lic5; // 等价于:type LicenseType = LicenseTypeMap[keyof LicenseTypeMap];
通过以上调整,既保留了原有的联合类型设计,又实现了基于字符串变量的自动类型推断,提升了类型安全性和开发体验。
内容的提问来源于stack exchange,提问作者JustBarnt
相关产品推荐
相关产品推荐

