有没有办法阻止TypeScript中的联合类型?

Bir*_*sky 7 functional-programming typescript

我是条件类型的新手,所以我尝试了最明显的静态方法,没有成功:

type NoUnion<Key> =
  Key extends 'a' ? 'a' :
  Key extends 'b' ? 'b' :
  never;

type B = NoUnion<'a'|'b'>;
Run Code Online (Sandbox Code Playgroud)

B型仍然是一个联盟.有人请你上学吗?

这是一个游乐场.

Tit*_*mir 10

我不能确定这种情况的用例是什么,但我们可以强制NoUnionnever如果传递的类型是union类型.

正如其他提到的条件类型在联合上分布一样,这称为分布式条件类型

检查类型是裸类型参数的条件类型称为分布式条件类型.分布式条件类型在实例化期间自动分布在联合类型上.例如,T的实例化扩展了U?X:Y,类型参数为A | B | T的C被解析为(A扩展U?X:Y)| (B扩展U?X:Y)| (C扩展U?X:Y).

键是'裸类型',如果我们将类型包装在元组类型中,例如条件类型将不再是分布式的.

type UnionToIntersection<U> = 
    (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never 

type NoUnion<Key> =
    // If this is a simple type UnionToIntersection<Key> will be the same type, otherwise it will an intersection of all types in the union and probably will not extend `Key`
    [Key] extends [UnionToIntersection<Key>] ? Key : never; 

type A = NoUnion<'a'|'b'>; // never
type B = NoUnion<'a'>; // a
type OtherUnion = NoUnion<string | number>; // never
type OtherType = NoUnion<number>; // number
type OtherBoolean = NoUnion<boolean>; // never since boolean is just true|false
Run Code Online (Sandbox Code Playgroud)

最后一个例子是一个问题,因为boolean是由编译器所看到true|false,NoUnion<boolean>实际上会never.如果没有更多关于你究竟想要实现的细节,很难知道这是否是一个交易破坏者,但它可以通过boolean作为一个特例来解决:

type NoUnion<Key> =
    [Key] extends [boolean] ? boolean :
    [Key] extends [UnionToIntersection<Key>] ? Key : never;
Run Code Online (Sandbox Code Playgroud)

注意:UnionToIntersection取自这里

  • @Birowsky :))编写docs时没有赞成票:P.这更有趣;) (2认同)

jca*_*alz 5

顺便说一句,我试图提出的“更简单”的代码是这样的:

type NotAUnion<T> = [T] extends [infer U] ? 
  U extends any ? [T] extends [U] ? T : never : never : never;
Run Code Online (Sandbox Code Playgroud)

这应该可以工作(请进行测试;不知道为什么我对另一个问题的回答是错误的,但是现在已经修复了)。这与的想法类似UnionToIntersection:如果您要T分配类型,则要确保将其分配给每个部分T。通常,只有T具有一个组成部分的联合(也称为“非联合”)才是正确的。

无论如何,@ TitianCernicovaDragomir的答案也很好。只是想在那里获得该版本。干杯。