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

如何编写仅允许更新对象类型值的TypeScript泛型函数?

解决方案

首先,你需要定义一个类型工具,用来提取对象中值为object类型的键(排除null,因为typeof null会返回object):

type ObjectKeys<T> = {
  [K in keyof T]: T[K] extends object ? K : never;
}[keyof T];

这个类型会遍历目标对象的所有键,只保留对应值为object类型的键,其他键会被映射为never,最终通过索引访问得到合法键的集合。

接下来修改你的updateDbItem函数,把泛型K的约束从keyof SItem改为ObjectKeys<SItem>,这样函数就只接受值为object类型的键:

enum SKey {
  key1 = "key1",
  key2 = "key2",
}

type SItem = {
  [SKey.key1]: boolean;
  [SKey.key2]: {
    attr1: string;
    attr2: boolean;
  };
};

const mapDB: SItem = {
  [SKey.key1]: true,
  [SKey.key2]: {
    attr1: "hello",
    attr2: true,
  },
};

// 过滤出值为object类型的键
type ObjectKeys<T> = {
  [K in keyof T]: T[K] extends object ? K : never;
}[keyof T];

export function updateDbItem<K extends ObjectKeys<SItem>>(
  key: K,
  newFields: Partial<SItem[K]>
) {
  const item = mapDB[key];
  mapDB[key] = { ...item, ...newFields }; // 此时TS能确定item是object类型,不会报错
}

效果验证

  • 调用合法键(key2):正常通过类型检查
    updateDbItem(SKey.key2, { attr1: "world" }); // ✅ 合法
    
  • 调用非法键(key1):直接触发类型错误,符合预期
    updateDbItem(SKey.key1, {}); // ❌ 类型错误:类型"SKey.key1"不能赋值给类型"SKey.key2"
    

错误原因说明

你之前遇到的TS2698错误,是因为原函数的泛型K允许所有keyof SItem,包括对应值为boolean的key1。TS无法保证mapDB[key]一定是object类型,因此不允许使用对象展开语法。通过ObjectKeys约束K后,TS能明确知道SItem[K]必然是object类型,展开操作就合法了。

内容的提问来源于stack exchange,提问作者Thomas Gak-Deluen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:17