无法缩小具有未定义属性的简单TypeScript联合类型

时间:2017-06-16 07:28:30

标签: typescript typescript2.0 type-systems union-types

我有两个联合类型,一个有属性而另一个没有。我认为检查该属性的存在将允许我缩小它,但它不起作用。

我创建了this Playground repro。其他very similar thing似乎工作正常。我是否以错误的方式使用工会?

以下是为了完整性而编写的代码:

export interface AuthenticatedProfile {
    readonly userId: string;
    readonly name: string;
}
export interface AnonymousProfile {
    readonly userId: undefined;
    readonly otherProp: string;
}
export type Profile = AnonymousProfile | AuthenticatedProfile;

function handleProfile(prof: Profile) {
    if (prof.userId) {
        console.log(prof.name);
    }
}

谢谢!

2 个答案:

答案 0 :(得分:3)

您可以使用类型防护来限制 prof 参数的类型。

export interface AuthenticatedProfile {
    readonly userId: string;
    readonly name: string;
}
export interface AnonymousProfile {
    readonly userId: undefined;
    readonly otherProp: string;
}
export type Profile = AnonymousProfile | AuthenticatedProfile;

function isAuthenticatedProfile(prof: Profile): prof is AuthenticatedProfile {
    return (<AuthenticatedProfile>prof).name !== undefined;
}

function isAnonymousProfile(prof: Profile): prof is AnonymousProfile {
    return (<AnonymousProfile>prof).otherProp !== undefined;
}

function handleProfile(prof: Profile) {
    if (isAuthenticatedProfile(prof)) {
        console.log(prof.name);
    } else if (isAnonymousProfile(prof)) {
        console.log(prof.otherProp);
    }
}

您可以在handbook的“高级类型”部分中阅读有关打字稿中类型警卫的更多信息。

答案 1 :(得分:2)

您可以执行以下操作:

export interface AuthenticatedProfile {
    readonly type: "AuthenticatedProfile";
    readonly userId: string;
    readonly name: string;
}

export interface AnonymousProfile {
    readonly type: "AnonymousProfile";
    readonly userId: undefined;
    readonly otherProp: string;
}

export type Profile = AnonymousProfile | AuthenticatedProfile;

function handleProfile(prof: Profile) {
    if (prof.type === "AnonymousProfile") {
        console.log(prof.name); // Error
        console.log(prof.otherProp); // OK
        console.log(prof.userId); // OK
    }
    if (prof.type === "AuthenticatedProfile") {
        console.log(prof.name); // OK 
        console.log(prof.otherProp); // Error
        console.log(prof.userId); // OK
    }
}