TypeScript使用动态键访问多类型值对象时能否收窄值类型?
你遇到的报错是TypeScript当前类型系统的默认限制导致的:当使用联合类型的动态key访问对象属性时,typeof判断只会收窄属性值的类型,不会反向将key收窄到「所有值类型匹配的key的联合」,因此赋值时TS无法匹配key和对应值的类型,才会抛出Type 'string' is not assignable to type 'never'错误。
以下是几个符合你需求的简洁方案,都不需要枚举所有key,扩展对象属性时也无需额外同步维护代码:
方案1:封装泛型赋值工具(最推荐)
封装一个通用的泛型赋值函数,TS会自动绑定key和对应值的类型,类型校验完全自动化:
interface TestObject { a: string b: number } type TestKeyType = keyof TestObject const myObjct = {a: "cat", b:34} as TestObject; const key = 'a' as TestKeyType; // 通用泛型赋值函数,可复用在所有同类场景 function setValue<T extends object, K extends keyof T>(obj: T, key: K, value: T[K]) { obj[key] = value } if (typeof myObjct[key] !== 'string') { throw TypeError(); } // 无报错,TS自动校验类型匹配 setValue(myObjct, key, 'dog');
方案2:类型断言(适合一次性简单场景)
如果你100%确认当前赋值的类型合法,可以直接用类型断言跳过校验,代码改动最小:
if (typeof myObjct[key] !== 'string') { throw TypeError(); } myObjct[key] = 'dog' as TestObject[TestKeyType];
方案3:泛型类型守卫(适合需要多次做类型判断的场景)
封装一个通用的类型守卫,可以直接收窄key到对应值类型的子集,后续取值、赋值都能被TS正确识别类型:
// 通用类型守卫:判断obj的key对应的值是否为指定类型 function isKeyMatchType<T extends object, V>( obj: T, key: keyof T, type: string ): key is keyof { [K in keyof T as T[K] extends V ? K : never]: T[K] } { return typeof obj[key] === type } if (!isKeyMatchType<TestObject, string>(myObjct, key, 'string')) { throw TypeError(); } // 类型已被正确收窄,无报错 myObjct[key] = 'dog';
内容的提问来源于stack exchange,提问作者melink14
相关产品推荐
相关产品推荐

