如何实现含类型安全转换函数的TypeScript接口映射?
解决方案
核心问题在于你当前的MapItem<keyof B>让transform的返回类型变成了B所有属性值的联合类型,导致错误的返回值无法被检测到。要实现类型安全的映射,需要让A的每个属性与B的特定属性绑定,同时让transform的参数和返回类型都与对应属性的类型关联。
步骤1:定义A到B的属性映射关系
首先创建一个类型,明确A的每个属性对应到B的哪个属性:
type AtoBMap = { first: 'foo'; second: 'bar'; };
步骤2:构建类型安全的Mapping类型
基于上述映射关系,定义Mapping类型,确保每个A的属性对应的key是B的指定属性,且transform的参数是A对应属性的value类型,返回值是B对应属性的非undefined类型或null:
type Mapping = { [K in keyof A]: { key: AtoBMap[K]; // 参数类型为A[K]['value'],而非unknown,提升类型安全性 transform: (value: A[K]['value']) => Exclude<B[AtoBMap[K]], undefined> | null; }; };
步骤3:使用类型安全的Mapping
现在你的mapping会严格校验transform的返回值类型,错误的返回会立即触发类型提示:
const mapping: Mapping = { first: { key: 'foo', transform: (value) => { if (value === 'Yes') return true; if (value === 'No') return false; return null; } }, second: { key: 'bar', // ❌ 类型错误:返回类型boolean不能赋值给string | null transform: (value) => typeof value === 'number' ? value >= 10 : null // ✅ 正确写法示例: // transform: (value) => typeof value === 'number' ? value.toString() : null } };
额外优化:让AtoBMap自动推导(可选)
如果你不想手动维护AtoBMap,可以让TypeScript自动推导映射关系,通过const断言实现:
const mapping = { first: { key: 'foo' as const, transform: (value: A['first']['value']) => { if (value === 'Yes') return true; if (value === 'No') return false; return null; } }, second: { key: 'bar' as const, // ❌ 同样会触发类型错误 transform: (value: A['second']['value']) => typeof value === 'number' ? value >= 10 : null } } satisfies { [K in keyof A]: { key: keyof B; transform: (value: A[K]['value']) => Exclude<B[typeof key], undefined> | null; }; };
使用satisfies关键字可以在保留自动推导的同时,确保结构符合类型约束。
内容的提问来源于stack exchange,提问作者Jared MacFarlane
相关产品推荐
相关产品推荐

