如何让TypeScript泛型Partial<Record>无需断言兼容Record<string,number>
解决方案:优化泛型选择类型以兼容
Record<string, number> 问题根源在于原Partial<Record<keyof T & string, 0 | 1>>类型被TypeScript判定为可能包含值为undefined的属性(虽然实际只有不存在的属性会返回undefined,存在的属性值都是0|1),而API要求的Record<string, number>不允许属性值为undefined。
我们可以通过类型交集重新定义泛型类型,同时保留键值校验能力和兼容性:
type SelectionType<T> = Partial<Record<keyof T & string, 0 | 1>> & Record<string, number>;
类型说明
Partial<Record<keyof T & string, 0 | 1>>:确保选择对象只能使用T的键,值只能是0或1,且所有字段可选;& Record<string, number>:让TypeScript明确该类型的所有属性值都是number(0和1都是number的子类型),从而直接兼容API的参数类型。
修改后的完整代码
interface ITest { keyA: string, keyB: string, keyC: string, } const testObj: ITest = {keyA: "aaaaaa", keyB: "bbbbbb", keyC: "cccccc"} // 不可修改的API函数 function printSelectedEntriesFromObject(processedObj: Record<string, any>, selectionObj: Record<string, number>) { console.log("##############################") for (const key in processedObj) { if (selectionObj[key] === 1) { console.log(`Entry: (${key},${processedObj[key]})`) } else { console.log(`Following key was excluded or not present at all selectionObj: ${key}`) } } } // 优化后的泛型选择类型 type SelectionType<T> = Partial<Record<keyof T & string, 0 | 1>> & Record<string, number>; // 校验示例(符合预期) const exampleSelectionObj1: SelectionType<ITest> = {} const exampleSelectionObj2: SelectionType<ITest> = {keyA: 1, keyC: 0} // 错误示例(符合预期) // const exampleSelectionObj3: SelectionType<ITest> = {keyA: 1, keyC: 50} // const exampleSelectionObj3: SelectionType<ITest> = {keyA: 1, NOT_EXISTING_KEY: 0} // 类型兼容,无TS错误 function versionWithGenericValidationOfSelectedKeys<T>(processedObj: Record<string, any>, selectionObj: SelectionType<T>) { printSelectedEntriesFromObject(processedObj, selectionObj) }
该方案无需使用类型断言,既保留了对选择对象的键值校验能力,又能直接适配API的Record<string, number>参数要求。
内容的提问来源于stack exchange,提问作者keldorn
相关产品推荐
相关产品推荐

