TypeScript中如何基于同实例字段收窄类型?
TypeScript 约束orgId与orgName的关联匹配问题
当前定义了Org类、orgs实例以及Data接口,但无法约束orgId和orgName的对应关系——当orgId为'ig'时,orgName填'Tiktok'不会触发报错,需要实现两者的强关联约束。
原代码如下:
class Org<Name extends string = string> { id: keyof typeof orgs; // 'tk' | 'ig' name: Name; constructor({id, name}) { this.id = id; this.name = name; } } const orgs = { tk: new Org({ id: 'tk', name: 'Tiktok' }), ig: new Org({ id: 'ig', name: 'Instagram' }) }; interface Data< A extends Org['id'] = Org['id'] > { orgId: A orgName: typeof orgs[A]['name'] } const test1: Data = { orgId: 'ig', orgName: 'Instagram' // 正确 } const test2: Data = { orgId: 'ig', orgName: 'Tiktok' // 应报错但未报错 }
解决方案
问题核心在于原Data接口的默认泛型参数会被推断为联合类型,导致orgName的类型变成所有可能名称的集合,无法实现强绑定。通过以下改动可解决:
class Org<Name extends string = string> { id: keyof typeof orgs; name: Name; constructor({id, name}: {id: keyof typeof orgs; name: Name}) { this.id = id; this.name = name; } } const orgs = { tk: new Org({ id: 'tk', name: 'Tiktok' }), ig: new Org({ id: 'ig', name: 'Instagram' }) } as const; // 锁定orgs的字面量类型,确保name为具体字符串值 // 生成orgId与orgName强绑定的联合类型 type Data = { [K in keyof typeof orgs]: { orgId: K; orgName: typeof orgs[K]['name']; } }[keyof typeof orgs]; const test1: Data = { orgId: 'ig', orgName: 'Instagram' // 正确,无报错 } const test2: Data = { orgId: 'ig', orgName: 'Tiktok' // 报错:类型 '"Tiktok"' 不能赋值给类型 '"Instagram"' }
关键改动说明
orgs添加as const断言:将orgs的类型从宽泛的Org<string>实例集合,转换为只读的字面量类型集合,确保每个name的类型是具体的字符串字面量('Tiktok'/'Instagram'),而非通用string。- 重构
Data为联合类型:通过映射类型遍历orgs的所有键,为每个键生成orgId与对应orgName的强绑定子类型,最后取所有子类型的联合,让Data成为{orgId: 'tk', orgName: 'Tiktok'} | {orgId: 'ig', orgName: 'Instagram'},自然约束两者的对应关系。
内容的提问来源于stack exchange,提问作者AKG
相关产品推荐
相关产品推荐

