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

如何在TypeScript的omit()函数泛型中保留特定string[]类型

解决方案

你可以通过TS 5.0新增的const类型参数修饰符解决这个问题,它会强制TypeScript不拓宽传入的字面量类型,完整类型定义如下:

declare function omit<
  O extends Record<string, unknown>,
  const P extends string | readonly string[]
>(
  source: O, 
  props: P
): Omit<O, P extends string ? P : P[number]>

测试效果完全符合预期:

const o1 = omit({ a: 1, b: 'foo', c: true }, 'b');
o1.a // 正常
o1.b // 报错
o1.c // 正常

const o2 = omit({ a: 1, b: 'foo', c: true }, ['b', 'c']);
o2.a // 正常
o2.b // 报错
o2.c // 报错

如果需要兼容TS 5.0以下的版本,也可以用函数重载实现,用户传入数组参数时手动加as const即可:

declare function omit<O extends Record<string, unknown>, P extends string>(source: O, props: P): Omit<O, P>
declare function omit<O extends Record<string, unknown>, P extends readonly string[]>(source: O, props: P): Omit<O, P[number]>

// 使用时
const o2 = omit({ a: 1, b: 'foo', c: true }, ['b', 'c'] as const);

原理说明

  1. 为什么普通数组参数会丢失字面量类型?
    TypeScript默认会对字面量数组做类型拓宽,比如['b', 'c']这种字面量默认会被推导为通用的string[]类型,而不是['b', 'c']元组类型,所以P[number]就会被推导为string,导致Omit把对象所有属性都移除。

  2. 为什么剩余参数可以保留字面量类型?
    这是TypeScript的设计特殊处理:剩余参数的作用是收集零散传入的单个参数,TS默认就会保留每个参数的字面量类型,合并为字面量元组,不会做自动拓宽,所以能准确拿到所有要删除的属性的联合类型。


内容的提问来源于stack exchange,提问作者shau-kote

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:45:00