2017-06-16 85 views
4

我有两个联合类型,一个有属性,另一个没有。我假设检查该财产的存在将允许我缩小它,但它不起作用。无法缩小具有未定义属性的简单TypeScript联合类型

我创建了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); 
    } 
} 

谢谢!

回答

3

您可以使用类型卫兵限制教授参数的类型。

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高级类型部分阅读更多关于类型的后卫在打字稿。

+0

您的解决方案看起来不错。我只有一个问题:如果属性userId是这两种类型的一部分,并且每种类型只能采用不相交的一组值,那么为什么TypeScript在我的原始检查后不能推断这种类型? –

+0

对我来说调用'prof.userId'没有任何类型的警卫工作得很好。 – toskv

+1

它实际上似乎是一个已知的问题。 https://github.com/Microsoft/TypeScript/issues/12600。不知道你为什么看不到这个错误,在操作系统repro中,我发布了 –

1

你可以做到以下几点:

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 
    } 
} 
+0

很高兴知道这个选择,但我会坚持不改变我的价值或类型的其他解决方案。但是我有一个问题:如果属性userId是这两种类型的一部分,并且每种类型只能采用不相交的一组值,那么为什么TypeScript在我的原始检查后不能推断出该类型? –

相关问题