一、 声明函数及其类型
对象的语法全都适用于函数。
// 第一种:先写类型再赋值
type F1 = (a: number, b: number) => number
const f1: F1 = (a, b) => a + b
// 第二种:先实现箭头函数,再获取类型
const f2 = (a: number, b: number): number => {
return a + b
}
type F2 = typeof f2
// 第三种:先实现普通函数,再获取类型
function f3(this: unknown, a: number, b: number): number {
return a + b
}
type F3 = typeof f3
// 第四种:先实现匿名普通函数,再获取类型
const f4 = function (this: unknown, a: number, b: number): number {
return a + b
}
type F4 = typeof f4
二、两种特殊函数
构造函数 与 类型谓词(is)
1. 构造函数
2. 类型谓词(is)
type Person = {
name: string
}
type Animal = {}
function f1(a: Person | Animal){
if (isPerson(a)){
a
}
}
function isPerson(x: Person | Animal): x is Person { //类型谓词
return 'name' in x
}
// 箭头函数形式
const isPerson2 = (x: Person | Animal): x is Person => {
return 'name' in x
}
三、TS 函数语法细节
1. 可选参数
// useCapture 为可选参数
function addEventListener(eventType: string, fn: unknown, useCapture ?: boolean){
console.log(eventType,fn,useCapture)
}
2. 参数默认值
// useCapture 既可选,又有默认值
// 写法一
function addEventListener(eventType: string, fn: unknown, useCapture = false){
console.log(eventType,fn,useCapture)
}
// 写法二
function addEventListener(eventType: string, fn: unknown, useCapture ?: boolean){
if(useCapture === undefined){
useCapture = false
}
console.log(eventType,fn,useCapture)
}
3. 参数也是函数
function addEventListener(
eventType: string, fn: (e: Event, el: Element) => void, useCapture = false
){
const element = {} as HTMLElement
const event = {} as Event
fn(event,element)
}
addEventListener('click',(e, el) => 1)
4. 返回值也是函数(函数柯里化)
// 平时写的函数
const add = (a: number, b: number) => a + b
add(6, 18)
// 函数柯里化,返回值是函数
// 写法一
const createAdd = (a: number) => {
return (b: number) => {
return a + b
}
}
// 写法一简写
const createAdd = (a: number) => (b: number) => a + b
// 写法二:把类型写出来
type CreateAdd = (x: number) => (y: number) => number
const createAdd: CreateAdd = a => b => a + b
createAdd(6)(18)
四、函数重载
同名函数可能参数类型不同,或者参数个数不同,或者都不同。(更推荐使用不同名函数)
// function createDate(n: number): Date
// function createDate(year: number, month: number, day: number): Date
function createDate(a: number, b?: number, c?: number): Date {
if (a !== undefined && b !== undefined && c !== undefined){
return new Date(a,b,c)
}else if (a !== undefined && b === undefined && c === undefined){
return new Date(a)
}else{
throw new Error('只接受一个或三个参数!')
}
}
createDate(2000000)
createDate(2022, 1, 1)
五、指定 this 类型
type Person = {
name: string
}
function f(this: Person, n: number) {
console.log(n)
}
// 1. person.f(1)
const p: Person & {f: typeof f} = { name: 'Bumble', f: f }
p.f(1)
// 2. f.call(person, 1)
const p2: Person = {name:'Bumble2'}
f.call(p2, 1)
// 3. f.apply(person, [1])
const p3: Person = {name:'Bumble3'}
f.apply(p3, [1])
// 4. f.bind(person)(1)
const p4: Person = {name:'Bumble4'}
const newF = f.bind(p4)
newF(1)
六、... 与参数
1. 剩余参数
剩余参数要放在最后。
function sum(name: string, ...array: number[]){
return array.reduce((result, n) => result + n, 0)
}
sum('Bumble',1)
sum('Bumble',1,2,3)
2. 展开参数
function sum(name: string, ...array: number[]){
f.apply(null, array) //方法一
f(...array) //方法二
}
function f(...array: number[]){
console.log(array)
}
3. as const
把一个值当作常量,类型推断收窄,表示类型不会变。一般用于数组对象或普通对象。
// JS 的 const 还是可以修改数组
const array = [1,'hi']
array = [2, 'hi'] //报错,数组不能被重新赋值
array.push(2) //不报错,虽然使用 const 声明数组,但是可以修改数组
const array = [1,'hi'] as const
array.push(2) //报错
function fn(a: number, b: number){
return a + b
}
// 如果不加 as const 就无法制约参数个数(因为数组是可修改的)
// 加 as const 之前的类型 number[]
// 加 as const 之后的类型 readonly [1,2]
const a = [1,2] as const
fn(...a)
4. 参数对象析构
type Config = {
url: string
method: 'GET' | 'POST' | 'PATCH' | 'DELETE'
data ?: unknown
headers ?: unknown
}
// //对象析构 //剩余参数 //默认参数
function ajax({url, method, ...rest}: Config = { method: 'GET', url:'' }){
console.log(url, method)
}
七、void 返回值类型
function f1(): void { //不报错
return
}
function f2(): void { //不报错
return undefined
}
function f3(): void { //不报错
}
function f4(): void { //报错
return null
}