否定打字稿类型? [英] Negating typescript types?

查看:110
本文介绍了否定打字稿类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Typescript中创建一个简单的NOT运算符,在该脚本中,您将所有原始组合成某种类型A的并集,这些原语不是第二种类型B的并集的原语成员.这可以使用条件类型来完成.例如,如果您有以下类型:

I wanted to create a simple NOT operator in typescript where you get all primitives combined into the union of some type A that are NOT primitive members of the union of a second type B. This can be done using conditional types. For example, if you have types:

type A = 'a' | 'b' | 'c';
type B = 'c' | 'd' | 'e'; 

...然后我想将它们映射到第三个派生类型[A-B],在这种情况下,它会产生:

... then I want to map them to a third derived type [A - B] that, in this case, would yield:

type C = 'a' | 'b'

使用以下所示形式的条件,这似乎是可行的.但是,我完全感到困惑,为什么下面的NOT运算符似乎给了我想要的东西,但是明确拼写出完全相同的条件逻辑却没有:

This seems to be doable using conditionals of the form shown below. HOWEVER, I am completely stumped why the NOT operator below seems to give me what I want, but explicitly spelling out the exact same conditional logic does not:

type not_A_B_1 = A extends B ? never : A;   // 'a' | 'b' | 'c'

type Not<T, U> = T extends U ? never : T;   
type not_A_B_2 = Not<A, B>                  // 'a' | 'b'

请参见有人可以告诉我我是否在这里缺少一些TS微妙之处,这可以解释为什么not_A_B_1not_A_B_2不相等吗?谢谢.

Could someone pls tell me if I'm missing some TS subtlety here that would explain why not_A_B_1 and not_A_B_2 are not equivalent? Thanks.

推荐答案

您遇到了

其中已检查类型为裸类型参数的条件类型称为分布式条件类型.实例化过程中,分布条件类型自动分布在联合类型上.例如,对于类型为T的类型为A | B | CT extends U ? X : Y实例化被解析为(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

Conditional types in which the checked type is a naked type parameter are called distributive conditional types. Distributive conditional types are automatically distributed over union types during instantiation. For example, an instantiation of T extends U ? X : Y with the type argument A | B | C for T is resolved as (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

所以在这里:

type not_A_B_1 = A extends B ? never : A;   // 'a' | 'b' | 'c'

A是具体类型,而不是类型参数,因此条件类型不会分布在其组成部分上.

The A is a concrete type, not a type parameter, so the conditional type does not get distributed over its constituents.

但是在

type Not<T, U> = T extends U ? never : T;   

T是裸类型参数,因此条件类型确实得到分发. 裸"是什么意思?它意味着T,而不是T的某些类型函数.因此,在{foo: T} extends W ? X : Y中,类型参数T是衣服"的,因此它不会分布.

the T is a naked type parameter, so the conditional type does get distributed. What does "naked" mean? It means T as opposed to some type function of T. So in {foo: T} extends W ? X : Y, the type parameter T is "clothed", so it doesn't distribute.

这导致一种不需要时可以关闭分布式条件类型的方法:给type参数穿上衣服.最简单且最不冗长的方法是使用元组的一个元素:

This leads to a way to turn off distributive conditional types when you don't want them: clothe the type parameter. The simplest and least verbose way to do this is to use a tuple of one element: So,

T extends U ? V : W // naked T
[T] extends [U] ? V : W // clothed T

由于[T] extends [U]T extends U时应为真,因此除分布性外,其余均等价.因此,让我们将Not<>更改为非分布式:

Since [T] extends [U] should be true exactly when T extends U, those are equivalent except for the distributivity. So let's change Not<> to be non-distributive:

type NotNoDistribute<T, U> = [T] extends [U] ? never : T;   
type not_A_B_2 = NotNoDistribute<A, B>                  // 'a' | 'b' | 'c'

现在not_A_B_2not_A_B_1相同.如果您喜欢原始的not_A_B_2行为,请使用Not<>之类的分布式条件类型.如果您喜欢非分配行为,请使用具体类型或衣服类型参数.那有道理吗?

Now not_A_B_2 is the same as not_A_B_1. If you prefer the original not_A_B_2 behavior, then use distributive conditional types like Not<>. If you prefer the undistributive behavior, use concrete types or clothed type parameters. Does that make sense?

顺便说一句,您的Not<T,U>类型已经以预定义类型在标准库中为 Exclude<T,U> ,意为从T中排除可分配给U的那些类型".

By the way, your Not<T,U> type is already present as a predefined type in the standard library as Exclude<T,U>, meant to "exclude from T those types that are assignable to U".

希望有帮助.祝你好运!

Hope that helps. Good luck!

这篇关于否定打字稿类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆