You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定义类型规则确保对象成员值为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辅助类型实现了校验,但存在两个小问题:

  1. 当约束不满足时,data的类型会变为never,报错信息不够直观
  2. 函数内部需要额外的if(data)判断,而实际上编译时已能确保data有效

上面的优化方案更简洁,类型约束逻辑直接明了,报错信息也更清晰。

内容的提问来源于stack exchange,提问作者Lordbalmon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:24:08