TypeScript如何从对象创建Map<keyof T,boolean>类型并修复泛型Argument报错
问题根因
- 定义的
Record<keyof T, any>要求传入对象必须覆盖T的所有属性,传入仅包含部分key的对象时会直接判定类型不匹配,是对象参数校验失效的核心原因。 - 现有类型未实现「基于给定对象生成键为
keyof T、值为boolean的映射类型」的需求,且classNames的入参style未绑定泛型约束,泛型推断链路不完整。
修复方案
调整Argument联合类型的对象分支,通过Partial将Record的属性转为可选,同时把值类型约束为boolean;给style参数补充泛型类型标注,支持自动推导泛型,无需手动传入类型。
修复后完整可运行代码:
type Argument<T> = | keyof T | (keyof T)[] | Partial<Record<keyof T, boolean>> export function classNames<T>(style: T) { const handleArgs = (args: Argument<T>[]) => { // 内部业务逻辑实现 } return (...args: Argument<T>[]) => handleArgs(args) } // 测试用例 const exampleObject = { prop1: {}, prop2: 2 } const myFunc = classNames(exampleObject) // TS自动推导T为typeof exampleObject,无需手动传泛型 myFunc('prop1') // 类型校验通过 myFunc('prop1', ['prop2']) // 类型校验通过 myFunc('prop1', ['prop2'], { prop2: true }) // 类型校验通过 myFunc('prop1', ['prop2'], { prop3: true }) // 类型校验不通过,prop3不属于exampleObject的属性 myFunc('prop1', ['prop2'], { prop2: 2 }) // 类型校验不通过,值类型不是boolean
补充说明
- 如果需要使用TS原生
Map结构而非对象字面量作为映射类型,直接将Argument的对象分支替换为Map<keyof T, boolean>即可,传入Map实例时会被正确校验。 - 补充
style: T约束后,TS会根据传入的style对象自动推导泛型T的类型,省去手动书写typeof exampleObject的步骤。
内容的提问来源于stack exchange,提问作者Kyle Johnson
相关产品推荐
相关产品推荐

