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

TypeScript泛型函数如何禁止对象出现非枚举的多余键

解决方案

核心问题出在你原来的Smth类型使用了[key: string]索引签名,TypeScript默认会允许索引签名覆盖范围内的任意多余属性,不会触发多余属性校验,所以才会出现非法字段不报错的问题。

解决思路是去掉泛型约束里的索引签名,改用额外的校验逻辑对每个传入的属性做逐字段校验,多余的键会被标记为never类型,触发精准的字段级报错,同时完全保留原有返回类型推导能力:

const enum SomeEnum {
  a = "a",
  b = "b",
}

// 定义允许出现的键集合
type AllowedKeys = keyof typeof SomeEnum | 'args'
// 原有属性的合法类型约束
type LegalEntryType = {
  args?: { [key: string]: () => string }
} & Record<SomeEnum, string>

// 校验逻辑:合法键保留原类型,非法键值类型设为never触发报错
type ValidateEntry<T> = T extends LegalEntryType 
  ? { [K in keyof T]: K extends AllowedKeys ? T[K] : never } 
  : LegalEntryType

// 保留原有返回类型逻辑不变
type FnReturn<S> = {
  [key in keyof S]: {
    [key2 in SomeEnum]: S[key] extends { args: any } ? () => string : string
  }
}

function f<S extends Record<string, object>>(obj: S & {[K in keyof S]: ValidateEntry<S[K]>}): FnReturn<S> {
  return null!
}

const t = f({
  prop1: {
    a: "abc",
    b: "def",
  },
  prop2: {
    args: {},
    a: "zzz",
    b: "xxx",
  },
  prop3: {
    a: "ok",
    b: "fine",
    oooops: "???", // 此处直接报错:不能将类型“string”分配给类型“never”,错误精准定位到当前非法字段
  }
})

效果说明

  • 非法多余字段会直接触发精准报错,错误标记在多余字段本身,不会影响其他合法字段的校验
  • 原有返回值推导完全和之前一致,变量t的类型和你给出的预期完全相同
  • 泛型逻辑完整保留,原有功能不受任何影响
  • 如果缺少必填的a/b字段、或者args类型不符合要求,也会正常触发对应报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:54:02