TypeScript笔记 —— 参数的可选类型

243 阅读3分钟

调用签名

在 JavaScript 中,函数除了可以被调用,自己也是可以有属性值的。然而前面讲到的函数类型表达式并不能支持声明属性。如果我们想描述一个带有属性的函数,我们可以在一个对象类型中写一个调用签名。

interface ICalcFn {
    name: string
    (num1: number, num2: number) : void
}

function calc(calcFn: ICalcFn) {
    console.log(calcFn.name)
    calcFn(10, 20)
}

注意这个语法跟函数类型表达式稍有不同,在参数列表和返回的类型之间用的是 : 而不是 =>。

构造签名

JavaScript 函数也可以使用 new 操作符调用,当被调用的时候,TypeScript 会认为这是一个构造函数(constructors),因为他们会产生一个新对象。你可以写一个构造签名( Construct Signatures ),方法是在调用签名前面加一个 new 关键词。

interface IPerson {
    new (name: string): Person
}

function factory(ctor: IPerson) {
    return new ctor('haha')
}

class Person {
    name: string
    constructor(name: string) {
        this.name = name
    }
}

factory(Person)

参数的可选类型

我们可以指定某个参数是可选的。

function foo(x: number, y?: number) {
    console.log(x, y)
}

这个时候这个参数y依然是有类型的,它是什么类型呢? number | undefined。

image.png 另外可选类型需要在必传参数的后面。

image.png

默认参数

从ES6开始,JavaScript是支持默认参数的,TypeScript也是支持默认参数的。

function foo(x: number, y: number = 6) {
    console.log(x, y)
}
foo(10)

这个时候y的类型其实是 undefined 和 number 类型的联合。

剩余参数

从ES6开始,JavaScript也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。

function sum(...nums: number[]) {
    let total = 0
    for(const num of nums){
       total += num
    }
    return total
}

const res1 = sum(10, 20, 30)
const res2 = sum(10, 20, 30, 40)

函数的重载

在TypeScript中,如果我们编写了一个add函数,希望可以对字符串和数字类型进行相加,应该如何编写呢?我们可能会这样来编写,但是其实是错误的。

image.png 那么这个代码应该如何去编写呢?在TypeScript中,我们可以去编写不同的重载签名(overload signatures)来表示函数可以以不同的方式进行调用。一般是编写两个或者以上的重载签名,再去编写一个通用的函数以及实现。

比如我们对sum函数进行重构。在我们调用sum的时候,它会根据我们传入的参数类型来决定执行函数体时,到底执行哪一个函数的重载签名。

function sum(a1: number, a2: number): number
function sum(a1: string, a2: string): string
function sum(a1: any, a2: any): any {
    return a1 + a2
}
console.log(sum(20, 30))
console.log(sum("aaa", "bbb"))

但是注意,有实现体的函数,是不能直接被调用的。

sum({name: 'haha'}, {age: 18})

我们现在有一个需求:定义一个函数,可以传入字符串或者数组,获取它们的长度。

这里有两种实现方案:

方案一:使用联合类型来实现;

方案二:实现函数重载来实现;

function getLength(a: string | any[]) {
    return a.length
}
function getLength(a: string): number
function getLength(a: any[]): number
function getLength(a: any) {
    return a.length
}

在可能的情况下,尽量选择使用联合类型来实现。