TypeScript中为什么无法通过该方式递增对象属性?
解决方案
报错的本质是string类型的prop无法保证是Test1 | Test2 | Test3上存在的合法索引,你不想给类型加索引签名放宽属性约束的话,可以选择以下两种适配方案:
方案1:编译期静态约束(更推荐)
用泛型约束prop一定是传入对象自身的合法键,从调用阶段就杜绝非法传参,不需要额外运行时判断:
type Test1 = { srn1: number } type Test2 = { srn2: number } type Test3 = { srn3: number } const test1: Test1 = { srn1: 1 }; const test2: Test2 = { srn2: 2 }; const test3: Test3 = { srn3: 3 }; // 泛型约束:prop 一定是传入 obj 自身的键 function incrementSrn<T extends Test1 | Test2 | Test3>(prop: keyof T, obj: T): void { obj[prop] += 1; } incrementSrn('srn1', test1); // 正常编译 incrementSrn('srn2', test1); // 编译报错,提前发现参数不匹配
方案2:运行时动态校验
如果prop是运行时才能确定的动态字符串,可以自定义类型守卫收窄索引类型,不需要修改原有类型定义:
// 通用类型守卫:判断 key 是否为 obj 的合法键 function isValidKey<T extends object>(key: PropertyKey, obj: T): key is keyof T { return key in obj; } function incrementSrn(prop: string, obj: Test1 | Test2 | Test3): void { if (isValidKey(prop, obj)) { // 进入判断分支后 TS 已经确认 prop 是 obj 的合法键,不会触发索引报错 obj[prop] += 1; } }
两种方案都不会修改原有Test1/Test2/Test3的类型约束,依然不允许声明外的额外属性。
内容的提问来源于stack exchange,提问作者Александр Макаров
相关产品推荐
相关产品推荐

