有没有一种方法可以防止TypeScript中的联合类型? [英] Is there a way to prevent union types in TypeScript?
问题描述
我是条件类型的新手,所以我尝试了最明显的静态方法,但没有成功:
type NoUnion<Key> =
Key extends 'a' ? 'a' :
Key extends 'b' ? 'b' :
never;
type B = NoUnion<'a'|'b'>;
B类型仍然是联合.有人可以教育我吗?
这是解决方案
我不确定用例是什么,但是如果传递的类型是联合类型,我们可以强制将NoUnion
更改为never
.>
正如其他提到的条件类型通过联合分布一样,这称为 最后一个示例是一个问题,因为编译器将 注意: I'm new to conditional types, so I tried the most obvious static way, no success: The B type is still a union. Would somebody please school me? Here's a playground. I am unsure what the usecase for this is, but we can force the As other mentioned conditional types distribute over a union, this is called distributive conditional types 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). The key there is 'naked type', if we wrap the type in a tuple type for example the conditional type will no longer be distributive. The last example is an issue, since Note: 这篇关于有没有一种方法可以防止TypeScript中的联合类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!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
boolean
视为true|false
,因此NoUnion<boolean>
实际上将是never
.如果没有更多关于您要实现的目标的详细信息,很难知道这是否会破坏交易,但是可以通过将boolean
作为特例来解决:type NoUnion<Key> =
[Key] extends [boolean] ? boolean :
[Key] extends [UnionToIntersection<Key>] ? Key : never;
UnionToIntersection
来自此处 type NoUnion<Key> =
Key extends 'a' ? 'a' :
Key extends 'b' ? 'b' :
never;
type B = NoUnion<'a'|'b'>;
NoUnion
to never
if the passed type is a union type.
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
boolean
is seen by the compiler as true|false
, NoUnion<boolean>
will actually be never
. Without more details of what exactly you are trying to achieve it is difficult to know if this is a deal breaker, but it could be solved by treating boolean
as a special case:type NoUnion<Key> =
[Key] extends [boolean] ? boolean :
[Key] extends [UnionToIntersection<Key>] ? Key : never;
UnionToIntersection
is taken from here