如何定义类型规则确保对象成员值为number并实现编译时检查
解决编译时确保
T[TName]为number类型的问题 问题描述
现有如下函数:
const secretFunc = <T extends object, TName extends keyof T>({ data, name }: { data: T name: TName }) => { const value = data[name] console.log(typeof value === 'number') }
该函数仅在运行时检查value是否为number,无法在编译时约束T[TName]必须是number类型,需要实现编译时的类型校验。
优化方案
不需要额外定义辅助类型,直接通过泛型约束即可实现更简洁、直观的编译时检查:
const secretFunc = <TName extends PropertyKey, T extends Record<TName, number>>({ data, name }: { data: T name: TName }) => { const value = data[name] // 此时value的类型已被TypeScript推断为number,无需运行时检查 console.log('value is number:', typeof value === 'number') }
方案说明
- 泛型约束
T extends Record<TName, number>直接限定:T必须是包含TName键的对象,且该键对应的值类型为number - 编译时如果传入的
data中name对应的属性不是number,或者name不是data的键,会直接抛出清晰的类型错误 - 函数内部无需额外的
if(data)判断,因为编译时已确保data符合约束条件
测试用例
- 合法调用(无编译错误):
secretFunc({ data: { label: 'five', value: 5 }, name: 'value' }) - 非法调用1(
name对应属性为string,编译报错):secretFunc({ data: { label: 'five', value: 5 }, name: 'label' }) - 非法调用2(属性值为string,编译报错):
secretFunc({ data: { value: '5' }, name: 'value' })
对比原方案
你的原方案通过NumberHost辅助类型实现了校验,但存在两个小问题:
- 当约束不满足时,
data的类型会变为never,报错信息不够直观 - 函数内部需要额外的
if(data)判断,而实际上编译时已能确保data有效
上面的优化方案更简洁,类型约束逻辑直接明了,报错信息也更清晰。
内容的提问来源于stack exchange,提问作者Lordbalmon
相关产品推荐
相关产品推荐

