繁体   English   中英

不排除打字稿联合类型

[英]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 看起来像PickOmit等实用程序类型,因此可以很好地与接口或具有属性的类型配合使用。

由于您的是联合类型,因此 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相同类型的所有属性。

作为副作用,当类型YOmit<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM