TypeScript 类型守卫

摘要:在本教程中,您将学习 TypeScript 中的类型守卫,以缩小变量的类型范围。

类型守卫允许您在条件块内缩小变量的类型范围。

typeof

让我们看一下以下示例

type alphanumeric = string | number;

function add(a: alphanumeric, b: alphanumeric) {
    if (typeof a === 'number' && typeof b === 'number') {
        return a + b;
    }

    if (typeof a === 'string' && typeof b === 'string') {
        return a.concat(b);
    }

    throw new Error('Invalid arguments. Both arguments must be either numbers or strings.');
}
Code language: TypeScript (typescript)

工作原理

  • 首先,定义alphanumeric类型,它可以保存字符串数字
  • 接下来,声明一个函数,该函数将两个变量ab相加,它们的类型为alphanumeric
  • 然后,使用typeof运算符检查两个参数的类型是否都是数字。如果是,则使用+运算符计算参数的总和。
  • 之后,使用typeof运算符检查两个参数的类型是否都是字符串。如果是,则连接两个参数。
  • 最后,如果参数既不是数字也不是字符串,则抛出错误。

在这个示例中,TypeScript 了解typeof运算符在条件块中的使用。在以下if块中,TypeScript 意识到ab是数字。

if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
}Code language: TypeScript (typescript)

类似地,在以下if块中,TypeScript 将ab视为字符串,因此您可以将它们连接成一个

if (typeof a === 'string' && typeof b === 'string') {
    return a.concat(b);
}
Code language: TypeScript (typescript)

instanceof

typeof运算符类似,TypeScript 也知道instanceof运算符的使用。例如

class Customer {
    isCreditAllowed(): boolean {
        // ...
        return true;
    }
}

class Supplier {
    isInShortList(): boolean {
        // ...
        return true;
    }
}

type BusinessPartner = Customer | Supplier;

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    }

    if (partner instanceof Supplier) {
        message = partner.isInShortList() ? 'Sign a new contract the supplier' : 'Need to evaluate further';
    }

    return message;
}
Code language: TypeScript (typescript)

工作原理

  • 首先,声明CustomerSupplier类。
    其次,创建一个类型别名BusinessPartner,它是CustomerSupplier的联合类型。
  • 第三,声明一个函数signContract(),它接受一个类型为BusinessPartner的参数。
  • 最后,检查合作伙伴是否是CustomerSupplier的实例,然后提供相应的逻辑。

在以下if块中,由于instanceof运算符,TypeScript 知道合作伙伴是Customer类型的实例

if (partner instanceof Customer) {
    message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
}Code language: TypeScript (typescript)

同样,TypeScript 知道合作伙伴是以下if块中的Supplier实例

if (partner instanceof Supplier) {
    message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
}Code language: TypeScript (typescript)

当 if 缩小一种类型时,TypeScript 知道在else中它不是那种类型,而是另一种类型。例如

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }
    return message;
}
Code language: TypeScript (typescript)

in

in运算符对对象上属性的存在进行安全检查。您也可以将其用作类型守卫。例如

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if ('isCreditAllowed' in partner) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract the supplier ' : 'Need to evaluate further';
    }
    return message;
}
Code language: TypeScript (typescript)

用户定义的类型守卫

用户定义的类型守卫允许您定义类型守卫或在使用函数时帮助 TypeScript 推断类型。

用户定义的类型守卫函数是一个函数,它只是返回arg is aType。例如

function isCustomer(partner: any): partner is Customer {
    return partner instanceof Customer;
}
Code language: TypeScript (typescript)

在这个示例中,isCustomer()是一个用户定义的类型守卫函数。现在您可以像下面这样使用它

function signContract(partner: BusinessPartner): string {
    let message: string;
    if (isCustomer(partner)) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }

    return message;
}
Code language: TypeScript (typescript)

总结

  • 类型守卫在条件块中缩小了变量的类型范围。
  • 使用typeofinstanceof运算符在条件块中实现类型守卫
本教程是否有用?