如何将带动态键的JS函数转为TypeScript并实现类型约束?
TypeScript 实现动态字段提取的类型约束
需求说明
需要将一段基于动态参数nameField和idField提取id(number类型)与name(string类型)的JavaScript函数转换为TypeScript代码,要求TypeScript能严格校验:
- 传入的
option参数必须包含指定的nameField和idField字段 nameField对应的字段值类型为string,idField对应的字段值类型为number
原JavaScript代码
export const foo = ( option, nameField = 'name', idField = 'id', ) => { const name = option[nameField]; const id = option[idField]; const result = { id, name }; /// ... other codes }
尝试的TypeScript代码
export const foo = <T extends Record<string, any>>( option: T, nameField: keyof T = 'name' as keyof T, idField: keyof T = 'id' as keyof T, ) => { const name = option[nameField]; const id = option[idField]; const result = { id, name }; /// ... other codes };
上述代码的问题在于Record<string, any>过于宽泛,无法约束nameField和idField对应字段的具体类型,达不到期望的校验效果。
期望校验效果
const option = { id: '1', // 应为number类型,不符合默认约束 name: 'Foo', value: 2 }; const a = foo(option); // 此处应触发错误 const b = foo(option,'name','value'); // 此处应正常通过校验
解决方案
通过泛型约束实现精准的类型校验,代码如下:
export const foo = < T extends Record<N, string> & Record<I, number>, N extends string = 'name', I extends string = 'id' >( option: T, nameField: N = 'name' as N, idField: I = 'id' as I ) => { const name = option[nameField]; const id = option[idField]; const result = { id, name }; /// ... 其他代码 return result; };
实现说明
- 泛型约束:
T extends Record<N, string> & Record<I, number>确保option中nameField(N类型)对应的字段是string,idField(I类型)对应的字段是numberN extends string = 'name'和I extends string = 'id'给泛型参数设置默认值,对应函数参数的默认值
- 参数默认值:通过
as N和as I类型断言解决默认值与泛型参数的类型匹配问题 - 自动校验:当使用默认参数调用时,TypeScript会检查
option的name和id字段类型;当传入自定义字段名时,会检查对应字段的类型是否符合要求
校验结果验证
- 调用
const a = foo(option);时,因为option.id是string类型,不符合默认idField对应的number要求,TypeScript会抛出类型错误 - 调用
const b = foo(option,'name','value');时,option.name是string、option.value是number,符合约束,代码正常通过校验
内容的提问来源于stack exchange,提问作者A.A
相关产品推荐
相关产品推荐

