陈述问题 随着 Typescript 的成长和流行,越来越多的 JavaScript 开发人员开始重视类型安全。Typescript 提供的功能列表非常庞大,可能让人应接不暇,因此在这篇文章中,我将重点介绍其中一个易于掌握且具有实用效果的功能。 让我们从一个例子开始。假设你正在开发一个具有许多用户角色的应用程序。一个应用程序被不同的用户使用是很常见的,不是吗?确切的角色在这里并不重要,但我们假设它们是 、 和 。在 typescript 中,我们可以声明拥有这些角色的用户,如下所示: admin consumer guest type Admin = {} type Consumer = {} type Guest = {} 现在,让我们考虑每个用户角色具有的一组属性。通常,它们是 、 和 或类似的。但是,等等, 用户可能不会有这些(毕竟他们是客人),所以我们暂时将此类型留空。 email firstName lastName Guest type Admin = { firstName: string lastName: string email: string } type Consumer = { firstName: string lastName: string email: string } type Guest = {} 应用程序的用户只能属于一个角色。通过类型来表示这一点的方法是使用 类型。 union type User = Admin | Consumer | Guest 管理员以其独特的能力而闻名,在我们的应用程序中,他们能够邀请消费者。让我们添加一个字段来指示管理员可以发送多少个邀请。 type Admin = { firstName: string lastName: string email: string numberOfInvitesLeft: number // <-- added } 为了让事情变得更有趣并且更接近真实的应用,让我们添加一个专属于 类型的属性。 Consumer type Consumer = { firstName: string lastName: string email: string premium: boolean // <-- added } 这是一个非常简单的例子,实际上,用户可能拥有数十种不同的属性,当您需要访问某些属性时,这会大大复杂化代码库。 const doSomethingBasedOnRole = (user: User) => { // how do you check here that user is really an admin if (user) { // ...and do something with the `numberOfInvitesLeft` property? } } 一个选择是检查该属性是否存在。 const doSomethingBasedOnRole = (user: User) => { if (user && user.numberOfInvitesLeft) { // safely access `numberOfInvitesLeft` property } } 但这是一个繁琐且不可扩展的解决方案。当“numberOfInvitesLeft”成为可选属性时该怎么办? 引入可区分联合类型 这就是可区分联合类型发挥作用的地方。我们只需要在每个用户类型中添加一个额外的字段来指示角色。 type Admin = { firstName: string lastName: string email: string numberOfInvitesLeft: number role: "admin" // <-- added } type Consumer = { firstName: string lastName: string email: string role: "consumer" // <-- added } type Guest = { role: "guest" // <-- added } 注意我如何将特定字符串作为类型;这称为 。这让您现在可以使用本机 JS 语言运算符(例如 、 、 来 角色。 字符串文字类型 switch case if else 区分 const user: Admin = { firstName: "John", lastName: "Smith", email: "johnsmith@examplemail.com", numberOfInvitesLeft: 3, role: "admin", } const doSomethingBasedOnRole = (user: User) => { if (user.role === "admin") { // now typescript knows that INSIDE of this block user is of type `Admin` // now you can safely call `user.numberOfInvitesLeft` within this block } } 这同样适用于 switch case 语句。 // ... const doSomethingBasedOnRole = (user: User) => { switch (user.role) { case "admin": { // now typescript knows that INSIDE of this block user is of type `Admin` // now you can safely call `user.numberOfInvitesLeft` within this block } case "consumer": { // do something with a `Consumer` user // if you try to call `user.numberOfInvitesLeft` here, TS compiler errors in // // "Property 'numberOfInvitesLeft' does not exist on type 'Consumer'." // } } } 可区分联合类型的好处是显而易见的,因为类型检查基于明确的角色属性,而不是可能与特定用户相关或不相关的临时属性。