TypeScript 允许指定函数的参数和返回值的类型。
-
函数声明的类型定义:
function 函数名(形参: 形参类型, 形参: 形参类型, ...): 返回值类型 {}
function sum(x: number, y: number): number { return x + y } sum(1, 2) // 正确 sum(1, 2, 3) // 错误。输入多余的或者少于要求的参数,都是不被允许的
-
函数表达式的类型定义:
const 函数名: (形参: 形参类型, 形参: 形参类型, ...) => 返回值类型 = function () {}
。对函数本身进行类型声明:
(形参: 形参类型, 形参: 形参类型, ...) => 返回值类型
。
对没有参数和没有返回值的函数本身进行类型声明:() => void
。// 不规范的写法。可以通过编译,但事实上只是对等号右侧的匿名函数进行了类型定义,而等号左边 sum 是赋值操作后进行类型推论而推断出来的,并没有对 sum 函数本身进行类型声明 const sum = function (x: number, y: number): number { return x + y }
// 规范的写法。在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。 const sum: (x: number, y: number) => number = function (x: number, y: number): number { return x + y } // 规范的写法还可以进行一些省略。在函数引用中定义好了函数的参数类型和返回值类型,那么函数体可以省略,不需要再次指定类型 const sum: (x: number, y: number) => number = function (x, y) { return x + y }
-
函数的调用签名(Call Signatures):函数除了作为函数本身可以被调用外,还可以作为对象有属性和方法。但是,函数声明的类型定义和函数表达式的类型定义并不支持声明属性和方法,此时可以使用函数的调用签名。
// 函数的调用签名的写法:可以用 Type,也可以用 interface type sumType = { // 对函数作为对象的属性值和方法的类型定义 name: string, // 对函数作为函数本身的类型定义。写法为 (参数列表): 返回值类型 (x: number, y: number): number, } const sum: sumType = function (x: number, y: number): number { return x + y } sum.name = 'sumFunc' sum(1, 2)
-
函数的构造签名:函数除了可以直接调用外,还可以使用 new 操作符调用,当通过 new 操作符调用时,TypeScript 就会认为这个函数是一个构造函数,会产生一个实例对象。此时,可以使用函数的构造签名。
对函数进行普通的函数类型定义,也可以使用 new 操作符来调用。但是,TypeScript 类型推断出来的实例对象的类型是 any。
class Person {} // 在调用签名前面加一个 new 关键词 type PersonType = { new (): Person, } function factory(callback: PersonType) { const p = new callback() return p } factory(Person) // 或者:在函数表达式前面加上 new 操作符 // function factory(callback: new () => void) { // const p = new callback() // return p // }
函数可选参数的类型定义:
可以用 ?
表示可选的参数,可选参数必须放在最后面。
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName
} else {
return firstName
}
}
let tomcat = buildName('Tom', 'Cat') // 正确
let tom = buildName('Tom') // 正确
在 ES6 中,允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数,但此时不受可选参数必须放在最后面的限制。
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName
}
let tomcat = buildName('Tom', 'Cat') // 正确
let cat = buildName(undefined, 'Cat') // 正确
函数重载的类型定义:
重载就是根据参数,选择相同函数名而参数不同的函数。严格来说,JS 中其实是没有函数重载的概念的。
在 TypeScript 中,可以去编写不同的重载签名来表示函数可以以不同的方式进行调用。一般是编写两个或者两个以上的重载签名,再去编写一个通用的函数实现。
// 实现函数接收两个参数,返回相加后的值。只能同时是数字,返回数字;或者同时是字符串,返回字符串
// 1. 先编写函数的重载签名:是没有实现体的
function add(arg1:number, arg2: number): number
function add(arg1:string, arg2: string): string
// 2. 然后编写通用的函数实现:是有实现体的
function add(arg1, arg2) {
return arg1 + arg2
}
// 3. 在调用函数的时候,会根据传入的参数类型来决定执行函数体时,执行哪一个函数的重载签名
add(10, 20) // 正确
add('Hello', 'World') // 正确
add(10, 'World) // 错误。调用的是函数的重载签名,通用函数不能被调用
函数中的 this 的类型:
this 的默认类型:
在没有对 TypeScript 进行特殊配置的情况下,函数中的 this 的默认类型是 any。
明确指定 this 的类型:
当在 tsconfig.json
配置文件中设置 compilerOptions 编译选项下的 noImplicitThis 为 true 时,表明不允许模糊的 this。此时,TypeScript 会根据上下文推断 this 的类型,如果能推断出具体的类型,不会报错;否则将会报错,此时就需要明确地指定 this 的类型。
需要将 this 作为函数的第一个参数来明确地指定类型。this 参数会在编译后会抹除。
function studying(this: {name: string}) {
console.log(this) // 正确
}
studying.call({name: 'Lee'})
this 相关的内置工具:
TypeScript 提供了一些工具类型来辅助进行常见的类型转换,这些类型全局可用。
-
ThisParameterType:用于获取一个函数类型中的 this 参数的类型。如果这个函数类型没有 this 参数的话,返回 unknown。
function studying(this: {name: string}) { console.log(this) } // 获取 studying 函数的类型 type studyingType = typeof studying // 获取 studyingType 类型中的 this 的类型 type studyingThisType = ThisParameterType<studyingType>
-
OmitThisParameter:用于移除一个函数类型中的 this 参数的类型,返回当前的函数类型。
function studying(this: {name: string}, ) { console.log(this) } // 获取 studying 函数的类型 type studyingType = typeof studying // 获取移除了 this 参数类型的纯净的函数类型 type pureStudyingType = OmitThisParameter<studyingType>
-
ThisType:用于绑定一个上下文的 this。
type StateType = { name: string, age: 18, } type StoreType = { state: StateType, studying: () => void, } const store: StoreType = { state: { name: 'Lee', age: 18, }, studying: function() { console.log(this.name) // 错误。此时 TypeScript 类型推断出的 this 是 store } }
可以通过明确地指定 this 的类型来解决。但是,如果有很多地方都需要用到 this,就会很繁琐。
const store: StoreType = { state: { name: 'Lee', age: 18, }, studying: function(this: StateType) { console.log(this.name) } } store.studying.call(store.state)
可以用 ThisType 来绑定一个上下文的 this。