TypeScript Exclude<UnionOfTypes, Interface> 是类型 "never"

TypeScript Exclude<UnionOfTypes, Interface> is type "never"

为什么下面的代码中 Exclude<A,B> 解析为 never 类型?打字稿编译器不能(通过静态分析)知道 AB 扩展 Parent 因此 Exclude<Choices, Parent> 应该解析为类型 C?

interface Parent {}

interface A extends Parent {}
interface B extends Parent {}
interface C {}

type Choices = A | B | C

type Test = Exclude<Choices, Parent> // = type "never"???

const c: C = {}
const d: Test = c // Type 'C' is not assignable to type 'never'

我可以硬编码 Parent = A | B 但我不确定为什么需要这样做。

这是因为 TypeScript 有 duck typing。具体来说,由于 CParent 是相同的接口,因此 C 可分配给 Parent.

具体来说,这个编译:

const c: C = {};
const p: Parent = c;

所以,尽管 C 没有明确地 extend Parent,TypeScript 仍然说 CParent.

如果您希望它起作用,只需向 Parent 添加 C 没有的内容即可。

interface Parent { foo: string }

interface A extends Parent {}
interface B extends Parent {}
interface C {}

type Choices = A | B | C

type Test = Exclude<Choices, Parent> // = type C

const c: C = {}
const d: Test = c // works!

我创建了一个文字工具如下

// It is the opposite operation to [exclude].
type Has<T, U> = U extends T ? U : never;

用法如下

    type A = {
      a : number;
      aa:number;
      aaa:number;
    }

    type B = {
      b : number;
    }

    type C = {
      c : number;
    }

    type D = {
      d : number;
    }


    // Here means the type A
    type Node_HasA = Has<{
      a : number;
    }, A|B|C|D>