如何基于已有接口的键值类型创建支持kind字段类型收窄的新类型
如何基于已有接口的键值类型创建支持kind字段类型收窄的新类型
嘿,这个问题我太熟了!你现在遇到的是TypeScript里常见的「关联类型未绑定」问题——你写的CompoundType虽然把kind和value的范围限制在了接口的键和值范围内,但两者之间没有建立一对一的对应关系,所以TypeScript没法自动根据kind来精准收窄value的类型,才会出现kind是bool1时还能传入字符串value的情况。
我给你一个简单直接的解决方案,核心是用映射类型转联合类型的方式,把接口的每个键值对绑定成独立的子类型,再组合成联合类型:
首先保留你原来的基础类型定义:
// 先定义你用到的DropdownItem类型 interface DropdownItem { label: string; value: string; } interface IFields { bool1: boolean; str1: string; dropDown: DropdownItem; }
然后修改CompoundType的定义:
export type CompoundType<T = IFields> = { [K in keyof T]: { kind: K; value: T[K] } }[keyof T];
我来拆解一下这个写法的逻辑:
- 第一步用
[K in keyof T]做映射类型,遍历接口T的每一个键K; - 对每个键
K,生成一个专属的对象类型:{ kind: K; value: T[K] }——这个类型里的kind被固定为具体的键名(比如'bool1'),value则严格对应这个键在接口里的类型(比如boolean); - 最后用
[keyof T]把整个映射类型“展开”成所有子类型的联合类型,简单说就是CompoundType现在等价于{kind: 'bool1', value: boolean} | {kind: 'str1', value: string} | {kind: 'dropDown', value: DropdownItem}。
现在你再测试代码就会发现类型检查完全符合预期了:
// 正确:kind是'bool1',value只能传boolean类型 const x: CompoundType = { kind: 'bool1', value: true }; // 错误:TypeScript会直接报错,提示'bool1'对应的value必须是boolean const y: CompoundType = { kind: 'bool1', value: 'xyz' }; // 正确:kind是'str1',value对应string类型 const z: CompoundType = { kind: 'str1', value: 'hello world' };
为什么原来的写法不行?因为你原来的CompoundType把kind定义为keyof T的联合,value定义为T[keyof T]的联合,这两个联合是完全独立的,TypeScript没法追踪它们之间的对应关系,自然做不到类型收窄。而新写法通过映射+联合的方式,把每一组kind和value的对应关系固化成了独立的类型,TypeScript就能准确识别它们的绑定关系啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

