暮年|细数这些年被困扰过的 TS 问题( 四 )

由于 TypeScript 是 JavaScript 的超集 , 因此以上的代码可以直接在 TypeScript 中使用 , 但当 TypeScript 编译器开启 noImplicitAny 的配置项时 , 以上代码会提示以下错误信息:
Parameter 'x' implicitly has an 'any' type.Parameter 'y' implicitly has an 'any' type.该信息告诉我们参数 x 和参数 y 隐式具有 any 类型 。 为了解决这个问题 , 我们可以为参数设置一个类型 。 因为我们希望 add 函数同时支持 string 和 number 类型 , 因此我们可以定义一个 string | number 联合类型 , 同时我们为该联合类型取个别名:
type Combinable = string | number;在定义完 Combinable 联合类型后 , 我们来更新一下 add 函数:
function add(a: Combinable, b: Combinable) {if (typeof a === 'string' || typeof b === 'string') {return a.toString() + b.toString();}return a + b;}为 add 函数的参数显式设置类型之后 , 之前错误的提示消息就消失了 。 那么此时的 add 函数就完美了么 , 我们来实际测试一下:
const result = add('semlinker', ' kakuqo');result.split(' ');在上面代码中 , 我们分别使用 'semlinker' 和 ' kakuqo' 这两个字符串作为参数调用 add 函数 , 并把调用结果保存到一个名为 result 的变量上 , 这时候我们想当然的认为此时 result 的变量的类型为 string , 所以我们就可以正常调用字符串对象上的 split 方法 。 但这时 TypeScript 编译器又出现以下错误信息了:
Property 'split' does not exist on type 'Combinable'.Property 'split' does not exist on type 'number'.很明显 Combinable 和 number 类型的对象上并不存在 split 属性 。 问题又来了 , 那如何解决呢?这时我们就可以利用 TypeScript 提供的函数重载 。
5.2 函数重载函数重载或方法重载是使用相同名称和不同参数数量或类型创建多个方法的一种能力 。
function add(a: number, b: number): number;function add(a: string, b: string): string;function add(a: string, b: number): string;function add(a: number, b: string): string;function add(a: Combinable, b: Combinable) {// type Combinable = string | number;if (typeof a === 'string' || typeof b === 'string') {return a.toString() + b.toString();}return a + b;}在以上代码中 , 我们为 add 函数提供了多个函数类型定义 , 从而实现函数的重载 。 在 TypeScript 中除了可以重载普通函数之外 , 我们还可以重载类中的成员方法 。
方法重载是指在同一个类中方法同名 , 参数不同(参数类型不同、参数个数不同或参数个数相同时参数的先后顺序不同) , 调用时根据实参的形式 , 选择与它匹配的方法执行操作的一种技术 。 所以类中成员方法满足重载的条件是:在同一个类中 , 方法名相同且参数列表不同 。 下面我们来举一个成员方法重载的例子:
class Calculator {add(a: number, b: number): number;add(a: string, b: string): string;add(a: string, b: number): string;add(a: number, b: string): string;add(a: Combinable, b: Combinable) {if (typeof a === 'string' || typeof b === 'string') {return a.toString() + b.toString();}return a + b;}}const calculator = new Calculator();const result = calculator.add('Semlinker', ' Kakuqo');这里需要注意的是 , 当 TypeScript 编译器处理函数重载时 , 它会查找重载列表 , 尝试使用第一个重载定义 。如果匹配的话就使用这个 。因此 , 在定义重载的时候 , 一定要把最精确的定义放在最前面 。 另外在 Calculator 类中 , add(a: Combinable, b: Combinable){ } 并不是重载列表的一部分 , 因此对于 add 成员方法来说 , 我们只定义了四个重载方法 。


推荐阅读