[英]Typescript union types not excluded
我有联合类型和Exclude
( 游乐场链接)的问题:
type Foo = {
data: string;
otherData: number;
};
type Bar = Omit<Foo,'otherData'>
// type Bar = { data: string; }; // Even this is not working
type FooBar = Foo | Bar;
type ShouldBeFoo = Exclude<FooBar, Bar>; // Not working
// ShouldBeFoo = never
type ShouldBeBar = Exclude<FooBar, Foo>; // Somehow working
// ShouldBeBar = { data: string }
我是否缺少与联合类型和/或Exclude
?
我也尝试过 TS 4.4 和 4.2,结果相同。
笔记:
由于keyof K
的第二个 arg 看起来像Pick
、 Omit
等实用程序类型,因此可以很好地与接口或具有属性的类型配合使用。
由于您的是联合类型,因此 TS 编译器无法推断出正确的行为。 你可以试试这个
type Foo = {
data: string;
otherData: number;
};
type Bar = Omit<Foo, 'otherData'>
type FooBar = Foo | Bar;
type Reduce<T, K> = T extends K ? K : never;
type ShouldBeFoo = Reduce<FooBar, Foo>;
type ShouldBeBar = Reduce<FooBar, Bar>;
Exclude 排除匹配而不是相等的类型。
您正在从FooBar
中排除Bar
。 Bar
匹配Bar
并且Bar
匹配Foo
。 所以你排除了两者。
你可以使用诸如
type ExcludeExact<T, U> = T extends U ? U extends T ? T : never : never
似乎真正的问题是误解了extends
检查在 TS 中的工作方式。 引用文档:
SomeType extends OtherType ? TrueType : FalseType;
当 extends 左边的类型可以赋值给右边的类型时,你会在第一个分支(“true”分支)中得到类型; 否则,您将在后一个分支(“假”分支)中获得类型。
在这种情况下, SomeType 不必是 OtherType 的显式扩展(在class SomeType extends OtherType
意义):足以将SomeType
分配给OtherType
,具有与OtherType
相同类型的所有属性。
作为副作用,当类型Y
是Omit<X, ...>
, X extends Y
检查总是通过 (!),因为Omit
只会减少属性的数量,但不会改变它们的类型和/或创建新的:
type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
现在,作为Exclude
generic 实际上看起来像这样:
type Exclude<T, U> = T extends U ? never : T
...您的联合类型( Foo | Bar
)通过extends Bar
检查就好了,因为联合的两个部分都通过了它。 但是, Bar extends Foo
检查失败,这就是为什么您的表达式适用于shouldBeBar
案例的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.