打字稿标记联合类型

Jam*_*s B 4 discriminated-union typescript

我想根据我的函数接收的接口来区分一些逻辑。为此,我尝试使用标记联合类型,例如,

someFunction(arg: TypeA | TypeB): void {
    if (arg.kind === "TypeA")
    {
        // do this
    }
    else
    {
        // do that
    }
}
Run Code Online (Sandbox Code Playgroud)

在哪里

interface TypeA {
    kind: "TypeA";
    propertyA: string;
}

interface TypeB {
    kind: "TypeB";
    propertyB: string;
}
Run Code Online (Sandbox Code Playgroud)

但是如果我想调用这个函数,Typescript 会抱怨我不提供 kind 的值,即,

let typeA: TypeA;
typeA = {propertyA: ""}
someFunction(typeA);
Run Code Online (Sandbox Code Playgroud)

TS2322: Type '{ propertyA: string; }' is not assignable to type 'TypeA'.
  Property 'kind' is missing in type '{ propertyA: string; }'.
Run Code Online (Sandbox Code Playgroud)

所以我不明白如果kind每次我想区分时都必须实现标签(在上面的例子中),标签类型是如何工作的。我只能假设我使用它们是错误的?

tos*_*skv 5

你可以定义一个类型保护来做到这一点。它们允许您通过参数的值或属性之一的存在来判断参数的类型。

function isTypeA(arg: TypeA | TypeB): arg is TypeA {
    return (<TypeA>arg).propertyA !== undefined;
}

function someFunction(arg: TypeA | TypeB): void {
    if (isTypeA(arg))
    {
      arg.propertyA;
    }
    else
    {
        arg.propertyB
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以阅读更多关于他们在这里检查工作的例子在这里