typescript - 据我了解,排除条件类型助手不起作用
问题描述
我一直在倾注 TypeScript 中的示例,试图了解Exclude
条件类型帮助器是如何独立工作的。
根据 TypeScript 文档的定义:
排除 - 从 T 中排除可分配给 U 的那些类型。
如库中所定义:
/**
* Exclude from T those types that are assignable to U
*/
type Exclude<T, U> = T extends U ? never : T;
我从用户那里看到了很多不正确的博客文章,并且我尝试了很多如下代码:
type User = {
id: string;
name: string;
phone: number;
isAdmin: boolean;
};
// Doesn't work below as standardUser still has all properties
type standardUser = Exclude<User, 'isAdmin'>;
我希望看到的standardUser
是一个type
已定义但没有isAdmin
属性的。结果是type standardUser
仍然具有所有相同的属性并且没有什么不同。我还使用了 aninterface
而不是type
别名,它表现出相同的行为。
查看TypeScript 文档,我看到提供的 (2) 个示例(当然还有使用理论上的文字和原语,而且根本翻译不好。
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T02 = Exclude<string | number | (() => void), Function>; // string | number
它们都可以工作,但我没有在这里翻译成现实世界的应用程序。然后我认为正如定义中提到的那样,它排除了可分配给另一个的类型,所以我尝试了这个:
type User = {
id: string;
isAdmin: boolean;
};
// Doesn't work below as standardUser still has all properties
type standardUser = Exclude<User, boolean>;
我再次希望看到它standardUser
被定义为一个类型,只有id
该boolean
类型应该被排除在外。我对这个原始助手的理解再次被取消。
我也尝试了一个enum
,这也没有减去任何值,并且新类型与所有可用值保持相同:
enum Fruits {
apple,
pear,
bananna
}
// Doesn't work below as redFruit still has all values
type redFruit = Exclude<fruits, 'pear' | 'bananna'>;
我也很清楚Exclude
通过keyOf
结合使用Pick
来创建一个Omit
类型,这最终可以很好地与我上面的第一个示例一起使用,以产生一个具有预期减去属性的类型:
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
好的,我Exclude
通过keyof T
将创建所需键的候选清单并Pick
完成其余的工作。但是,我仍然非常想了解帮助程序的非理论用例示例Exclude
以及它如何独立工作。对我来说,如果Exclude
按照我的想法工作,我就不需要创建Omit
类型。文档中的那些人为示例可能非常适合 2 个字符串文字列表,但我想知道如何Exclude
与interface
or type
please 结合使用?还是我误解了它的用法,它应该始终与keyof?
解决方案
type User = {
id: string;
name: string;
phone: number;
isAdmin: boolean;
};
// Doesn't work below as standardUser still has all properties
type standardUser = Exclude<User, 'isAdmin'>;
Exclude
适用于类型。从您的示例中,您似乎不想Exclude
处理类型,而是处理属性 -'isAdmin'
是属性名称,而不是示例中的类型。
但是,我仍然非常想了解 Exclude 帮助器的非理论用例示例以及它如何独立工作。对我来说,如果 Exclude 像我认为的那样工作,我就不需要创建 Omit 类型。
不幸的是,它并没有像你想象的那样工作。实际上,Exclude
它不是理论上的,而是允许您构建所需类型的低级构建块,例如Omit
. 在不使用中间类型 like的情况Omit
下,您可以通过以下方式获得所需的类型User
:
type standardUser = { [k in Exclude<keyof User, 'isAdmin'>]: User[k] };
这是逐步构建的相同类型:
type Step1 = keyof User; // get union type of User keys
// type Step1 = "id" | "name" | "phone" | "isAdmin"
type Step2 = Exclude<Step1, 'isAdmin'>; // remove "isAdmin" from union type
// type Step2 = "id" | "name" | "phone"
type Step3 = { [k in Step2]: User[k] }; // mapped type
// see https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types
// same as user, but without 'isAdmin' key
// type Step3 = { id: string; name: string; phone: number; }
但我想知道 Exclude 如何与接口或类型结合使用
一般来说,根据所有可能值的集合来考虑类型是有帮助的。例如,User
可以将类型视为一组具有所有 4 个属性的所有对象:“id”、“name”、“phone”、“isAdmin”,每个属性都有适当的类型。所以本质上它与 4 种类型的交集相同:
{id: string} & {name: string} & {phone: string} & {isAdmin: boolean}
如果要删除isAdmin
属性,实际上是在扩展符合新类型的对象集 - 为了符合,对象现在必须只有 3 个属性,而不是全部 4 个。换句话说,“普通”用户集更大而不是一组“管理员”用户。因此Exclude
,“缩小”类型在这里没有直接帮助。Exclude
在联合类型上效果最好,其中keyof
最常用。
推荐阅读
- html5-canvas - 选择框被拖动,但不是对象
- mysql - 如何插入批量记录
- java - 如何忽略列数中的最后一列?我正在使用 Apache POI 读取 excel 数据
- java - 如何在java中的映射中查找值的出现
- python - 如何使用按钮向导生成新的潜在客户?
- git - 如何删除(壁球)未命名的 git 分支
- php - 如果 ";" 是否有任何额外的解释器负载 设置到下一行?
- gmail - 从 AWS SES 发送 AMP 电子邮件时,GMAIL 上未显示
- php - 从复选框传递值并将它们显示在 Laravel 的另一个页面中的问题
- swift - 如何使用 indexpathforselectedrow 从我的结构数组中获取实例?