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

TypeScript如何通过排除特定字符串限制对象键名?

解决方案

1. 修复MutationRecord的键约束问题

你当前的MutationRecord定义无法禁止特定键,因为Exclude<string, "id" | "versionstamp" | "value">在TypeScript中仍然等价于string(string是所有字符串字面量的超集,排除有限几个值后还是string)。要真正禁止指定键,需要通过映射类型+never类型来实现:

type KvValue = string | number | boolean;
type Mutation<T extends KvValue> = (value: T) => KvValue;

// 定义禁止使用的键集合
type ForbiddenKeys = "id" | "versionstamp" | "value";

type MutationRecord<T extends KvValue> = {
  // 允许除禁止键外的所有字符串键,类型为Mutation<T>
  [K in Exclude<string, ForbiddenKeys>]: Mutation<T>;
} & {
  // 禁止键的类型设为never,赋值时会触发类型错误
  [K in ForbiddenKeys]: never;
};

// 错误示例:赋值id会触发类型报错(类型'(n: number) => number'不能赋值给类型'never')
const invalidRecord: MutationRecord<number> = {
  id: (n) => n * 2,
};

// 正确示例
const validRecord: MutationRecord<number> = {
  increment: (n) => n + 1,
  multiply: (n) => n * 2,
};

2. 交叉类型中保留禁止键的原类型

如果直接使用T & MutationRecord<T>,禁止键的类型会被never覆盖(因为T['id'] & never等于never)。要保留T中禁止键的原类型,需要通过Pick+Omit手动合并类型:

// 假设T是包含禁止键的类型
type ExampleT = {
  id: string;
  versionstamp: string;
  value: number;
  name: string; // 非禁止键
};

// 定义合并类型:保留T中的禁止键,其余键使用MutationRecord的类型
type CombinedType<T, U extends KvValue> = 
  Pick<T, ForbiddenKeys> & Omit<MutationRecord<U>, ForbiddenKeys>;

// 使用示例
const combined: CombinedType<ExampleT, number> = {
  id: "123", // 保留ExampleT中id的string类型
  versionstamp: "v1", // 保留原类型
  value: 456, // 保留原类型
  increment: (n) => n + 1, // 非禁止键,类型为Mutation<number>
};

简化版合并类型

如果不需要复用MutationRecord,也可以直接定义合并类型:

type CombinedType<T, U extends KvValue> = 
  Pick<T, ForbiddenKeys> & {
    [K in Exclude<string, ForbiddenKeys>]: Mutation<U>;
  };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 01:23:33