TypeScript 是一种强类型的 JavaScript 超集,它为开发者提供了更好的类型检查和代码提示功能。在 TypeScript 中,我们可以使用类型守卫(Type Guard)来帮助我们更好地处理类型检查。
本文将介绍 TypeScript 中类型守卫的概念、如何正确使用类型守卫以及一些常见的类型守卫场景。
什么是类型守卫?
类型守卫是一种 TypeScript 中的类型检查机制,它可以让我们在代码中更准确地判断变量的类型。
在 JavaScript 中,我们可以使用 typeof
或 instanceof
来判断变量的类型。但是在 TypeScript 中,由于类型的存在,这些方法可能会失效。
例如,下面的代码中,我们定义了一个 Person
类和一个 Cat
类,并创建了一个 Animal
类型的变量 animal
。我们使用 typeof
来判断 animal
的类型,但是 TypeScript 编译器会提示错误:
-- -------------------- ---- ------- ----- ------ - ----- ------- ---- ------- - ----- --- - ----- ------- ------ ------- - --- ------- ------ - ---- -- ------- ------ --- --------- - ------------------------- -- ------ -------- ------ ---- --- ----- -- ---- ------- - ----- -
这是因为 typeof
只能判断基本类型,而不能判断复杂类型。所以我们需要使用类型守卫来判断变量的类型。
如何正确使用类型守卫?
在 TypeScript 中,类型守卫有多种实现方式。下面是几种常见的类型守卫实现方式。
typeof 类型守卫
对于基本类型,我们可以使用 typeof
来进行类型守卫。
例如,下面的代码中,我们定义了一个 sum
函数,它接收两个参数,如果这两个参数都是 number
类型,那么返回它们的和,否则返回 NaN
。我们使用 typeof
来判断参数的类型:
-- -------------------- ---- ------- -------- ------ -------- -- --------- ------ - -- ------- - --- -------- -- ------ - --- --------- - ------ - - -- - ---- - ------ ---- - - ------------------ ---- -- ------- - -------------------- ---- -- ------- ---
instanceof 类型守卫
对于类的实例,我们可以使用 instanceof
来进行类型守卫。
例如,下面的代码中,我们定义了一个 Animal
类和一个 Cat
类,它继承自 Animal
类。我们创建了一个 Cat
类型的变量 cat
,然后使用 instanceof
来判断它的类型:
-- -------------------- ---- ------- ----- ------ - ----- ------- - ----- --- ------- ------ - ------ ------- - --- ---- --- - --- ------ -------- - ------ --------- - -------- -- ---- ---------- ---- - ----------------- -- - --- ----- ------------ ---- ----- ---------------- - ---- - ----------------- -- --- - ------- -
自定义类型守卫函数
对于复杂类型,我们可以使用自定义类型守卫函数来进行类型守卫。
例如,下面的代码中,我们定义了一个 Person
类和一个 Cat
类,它们都有一个 name
属性。我们创建了一个 Animal
类型的变量 animal
,然后使用一个自定义类型守卫函数 isPerson
来判断它的类型:
-- -------------------- ---- ------- ----- ------ - ----- ------- ---- ------- - ----- --- - ----- ------- ------ ------- - --- ------- ------ - ---- -------- ---------------- ------ - ----- ------ -- ------ - ------ ------- -- ----------- --- ---------- - -- ------------------ - ----------------- -- - ------ ----- --------------- ---- --- ----------------- - ---- - ----------------- -- - --- ----- --------------- ---- ----- ------------------- -
在上面的代码中,我们定义了一个 isPerson
函数,它接收一个 Person | Cat
类型的参数,并返回一个布尔值。当这个参数是 Person
类型时,返回 true
,否则返回 false
。在 if
语句中,我们使用 isPerson
函数来判断 animal
的类型。
常见的类型守卫场景
类型守卫与联合类型
在 TypeScript 中,联合类型是指一个变量可以是多种类型中的一种。例如,下面的代码中,我们定义了一个 Person
类和一个 Cat
类,然后创建了一个 Person | Cat
类型的变量 animal
:
-- -------------------- ---- ------- ----- ------ - ----- ------- ---- ------- - ----- --- - ----- ------- ------ ------- - --- ------- ------ - ----
当我们使用 animal
变量时,由于它可以是 Person
类型或 Cat
类型,所以 TypeScript 编译器无法准确地判断 animal
的类型。这时,我们可以使用类型守卫来帮助编译器判断变量的类型。
例如,下面的代码中,我们使用自定义类型守卫函数 isPerson
来判断 animal
的类型:
-- -------------------- ---- ------- -------- ---------------- ------ - ----- ------ -- ------ - ------ ------- -- ----------- --- ---------- - -- ------------------ - ----------------- -- - ------ ----- --------------- ---- --- ----------------- - ---- - ----------------- -- - --- ----- --------------- ---- ----- ------------------- -
在上面的代码中,我们使用 isPerson
函数来判断 animal
的类型。如果 animal
是 Person
类型,就输出人的信息;否则就输出猫的信息。
类型守卫与可选属性
在 TypeScript 中,我们可以为类的属性指定可选属性,即这个属性可以有值,也可以没有值。例如,下面的代码中,我们定义了一个 Person
类和一个 Cat
类,它们都有一个可选的 age
属性:
-- -------------------- ---- ------- ----- ------ - ----- ------- ----- ------- - ----- --- - ----- ------- ------ ------- ----- ------- -
当我们使用 age
属性时,由于它是可选属性,所以 TypeScript 编译器无法准确地判断这个属性是否存在。这时,我们可以使用类型守卫来判断属性是否存在。
例如,下面的代码中,我们使用自定义类型守卫函数 hasAge
来判断 animal
是否有 age
属性:
-- -------------------- ---- ------- -------- -------------- ------ - ----- ------ -- ------ - ------ ------- -- ----------- --- ---------- - --- ------- ------ - - ----- ----- -- --- ---- --- - - ----- -------- ------ ------- -- -- ---------------- - ----------------- -- - ------ ----- --------------- ---- --- ----------------- - ---- - ----------------- -- - --- ----- ------------ ---- ----- ---------------- -
在上面的代码中,我们使用 hasAge
函数来判断 animal
是否有 age
属性。如果 animal
有 age
属性,就输出人的信息;否则就输出猫的信息。
总结
类型守卫是 TypeScript 中的一个重要特性,它可以帮助我们更准确地判断变量的类型。在本文中,我们介绍了类型守卫的概念、如何正确使用类型守卫以及一些常见的类型守卫场景。希望本文可以帮助大家更好地使用 TypeScript。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/660684d1d10417a2224d08d7