TypeScript类型防护未意识到减少了字符串并集

时间:2019-04-25 09:50:56

标签: typescript

在下面的代码中,我希望TypeScript应该能够意识到在注释行中,user对象不能具有role的其他任何值,而admin的期望值是

有点!如果将这段代码粘贴到TypeScript Playground中,您将注意到此时悬停在role上确实确实显示了admin

但是,return DemoForAdmin行仍显示错误。然后将鼠标悬停在user上方,显示类型的弹出窗口将显示role字段的完整并集。

function Demo(user: { name: string; role: 'user' | 'admin'; } | null) {
    if (user === null) {
        return 'You have to be logged in.';
    }

    if (user.role !== 'admin') {
        return 'You have to be an admin';
    }

    user.role; // Hover over role to see "admin"
    return DemoForAdmin(user);
}

function DemoForAdmin(user: { name: string; role: 'admin'; }) {
    return 'You are an admin';
}

TypeScript不能意识到将对象传递给该方法是安全的(是吗?),并且在两种情况下都应该能够推断出正确的窄字符串并集{{1} }以及user,而不仅仅是role

1 个答案:

答案 0 :(得分:2)

类型保护仅适用于该字段,并且仅缩小该字段的范围,类型保护不会影响包含的对象类型。

还有另一种允许您执行此操作的结构,称为区分联合。该类型必须是对象类型的并集,并且要具有直角形类型的判别式。在这种情况下,可以使用role。这应该有效

function Demo(user: { name: string; role: 'user' } | { name: string; role: 'admin'; } | null) {
    if (user === null) {
        return 'You have to be logged in.';
    }

    if (user.role !== 'admin') {
        return 'You have to be an admin';
    }

    user.role; // Hover over role to see "admin"
    return DemoForAdmin(user);
}

function DemoForAdmin(user: { name: string; role: 'admin'; }) {
    return 'You are an admin';
}

您可以详细了解受歧视的工会here