跳到主要内容

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.');
}

怎么运行的:

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

在此示例中,TypeScript 知道条件块中 typeof 运算符的用法。 在下面的 if 块中,TypeScript 意识到 ab 是数字。

if (typeof a === 'number' && typeof b === 'number') {
return a + b;
}

同样,在下面的 if 块中,TypeScript 将 ab 视为字符串,因此,可以将它们连接成一个:

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

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;
}

怎么运行的:

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

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

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

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

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

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;
}

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;
}

用户定义的类型保护

用户定义的类型保护允许你定义类型保护或帮助 TypeScript 在使用函数时推断类型。

用户定义的类型保护函数是简单返回 arg is aType 的函数。 例如:

function isCustomer(partner: any): partner is Customer {
return partner instanceof Customer;
}

在此示例中,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;
}

概括

  • 类型保护缩小了条件块中变量的类型。
  • 使用 typeofinstanceof 运算符在条件块中实现类型保护