为什么 TypeScript 的 Omit 不强制执行省略属性的值?

问题描述 投票:0回答:2

背景:(可跳过)

我正在摆弄一些

update(person: Person)
语句,通过允许它应该更新的属性子集来使其更可用。我想有两个选择:

  • id 作为第一个参数显式传递给 update 方法,然后
    Partial<Person>
    Omit<Person, 'id'>
    作为第二个参数。
  • 或者,更新方法的签名保持原样,只有 1 个输入参数,并强制
    id
    属性位于提供的对象中。

所以

Omit
对我来说似乎是一个不错的候选者,但要省略的键可以是任何字符串值。

问题:

为什么 TypeScript 不强制提供给

Omit
的键值?我正在监督的还有什么好的用途吗?

看下面的代码

export interface Person {
  id: string;
  age: number;
  name: string;
}

type UpdatePerson = Omit<Person, 'whatEver'>; // Why does 'whatEver' not cause compile issues?
type UpdatePerson2 = Pick<Person, 'id'> & Partial<Person>; // Great, a valid key is enforced here
type UpdatePerson3 = Pick<Person, 'thisDoesNotCompile'> & Partial<Person>; // This line fails compilation as that property isn't part of the interface

现在我选择

update(person: UpdatePerson)
type UpdatePerson = Pick<Person, 'id'> & Partial<Person>;
。这使得所有属性都是可选的,而 id 是强制的。

typescript interface strong-typing typescript-utility
2个回答
4
投票

简而言之,选择此行为是为了使 内置

Omit
可以与现有的 DefinelyTyped 库最兼容。这些库已经在 Omit 是否应该严格的问题上存在分歧,选择更宽松的 Omit 可以防止这些现有库被破坏,但代价是编译器安全性和尚未编写的代码的自动完成功能稍差。


背景信息:这是在 microsoft/TypeScript#30825 中请求的,来自 DanielRosenwasser此响应

根据 DefinelyTyped 中的声明,受约束的

Omit
类型似乎会让至少一半的用户感到不满意。我们决定采用更宽松的内置功能,您可以在其中建立自己的约束。

这些来自语言合著者Ryan Cavanaugh

我必须澄清这个误解。 DT 上的 Omit 有 12 种不同的定义,其中两种最流行的定义在是否限制 [原文如此] 键上有所不同:[snip]

你可以挑选数字并尝试宣布民主多数或其他什么,但现实是,只有一个定义不会打破很大一部分人。

这是一个很受欢迎的请求,有重复项在 SO在 GitHub,相应的简洁严格等价物很容易编写/导出,并且在其他库中也可用,例如

type-zoo


0
投票

TypeScript 中内置的 Omit 实用程序是这样实现的:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

请注意,

K
受到 keyof any 的约束,它允许任何基于字符串的键,即使是
T
上不存在的键。这种设计允许灵活性,但牺牲了
K
中按键的严格性。

为了制作一个更安全的 Omit 版本,确保仅可以省略

T
上存在的键,您可以通过对
K
进行更严格的约束来重新定义它:

type StrictOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

在此自定义 StrictOmit 中,

K
专门限制为
keyof T
,这意味着只有
T
上实际存在的属性才能指定为省略。如果您尝试省略
T
上不存在的键,TypeScript 将引发错误。

要结束,只需将自定义类型放入

global.d.ts
即可开始。

© www.soinside.com 2019 - 2024. All rights reserved.