如何在TypeScript泛型数组中对单个元素取keyof并做独立类型校验
解决方案
首先你需要调整泛型的作用域,把每个映射项的目标类型校验下放到单个项的维度,而不是在函数全局声明固定的目标类型,具体实现如下:
- 首先重命名映射类型,避免和JS内置
Map类型冲突:
type Table<ExtT> = { id: number name: string } & ExtT // 重命名避免和原生Map冲突 type TableMap<SourceT, TargetT> = { name: string, map: { from: keyof SourceT, to: keyof TargetT } }
- 新增一个柯里化的辅助构造函数,先绑定统一的源类型(也就是你例子里的
tC),再给每个单独的映射项指定不同的目标类型,在创建阶段就完成类型校验:
// 第一步传入源类型,返回绑定了源类型的构造函数 const createTableMap = <SourceT extends object>() => { return <TargetT extends object>(mapItem: TableMap<SourceT, TargetT>) => mapItem }
- 调整
doSomething的类型定义,仅约束统一的源类型即可:
const doSomething = <SourceT extends object>(maps: TableMap<SourceT, any>[]) => { // 你的业务逻辑 }
用法示例
先提前定义好你的业务类型:
// 示例业务类型 type tA = Table<{prop1: string, prop2: string}> type tB = Table<{foo: string, bar: string}> type tC = Table<{cProp1: string, cProp2: string}>
调用时先绑定源类型,再创建每个映射项即可实现你要的校验效果:
// 先绑定本次调用统一的源类型为tC const createTfMap = createTableMap<tC>() doSomething([ createTfMap<tB>({ name: 'map1', map: { from: 'cProp1', // 校验通过:cProp1是tC的属性 to: 'foo' // 校验通过:foo是tB的属性 } }), createTfMap<tA>({ name: 'map1', map: { from: 'cProp1', to: 'bar' // 校验失败:bar不是tA的属性,符合预期 } }) ])
原代码问题说明
你之前的写法里把S泛型声明在了doSomething的顶级,意味着整个数组所有映射项的目标类型S必须是同一个,没法支持每个项用不同的目标类型做校验。把泛型下放到单个映射项的创建环节后,就能实现每个项独立校验的需求。
内容的提问来源于stack exchange,提问作者Gopikrishna S
相关产品推荐
相关产品推荐

