type MyFunction = (a: string) => void

表示函数:

  • 参数:一个,名称是 a,类型是字符串
  • 返回值:不返回任何值

参数

在每个参数后面加上类型注解来声明函数接受什么类型的参数,参数类型注释位于参数名称之后

function myfunc(name: string, age: number) {
  // ...
}

可选参数

使用 ? 表示这个参数是可选的

function f(x?: number) { // x 实际上的类型为 number | undefiend
  // ...
}

剩余参数

剩余参数的类型会被隐式设置为 any[],可以显示设置为 Array<T> 或者 T[] 或 元组类型

function multiply(n: number, ...m: number[]) {
  return m.map((x) => n * x)
}
 
const a = multiply(10, 1, 2, 3, 4)

但是如果先把数组赋值给一个变量,再传入函数会出现问题,因为 TS 假定数组是会变的:

function multiply(n: number, ...m: number[]) {
  return m.map((x) => n * x)
}
 
const arr = [1, 2, 3, 4]
const a = multiply(10, ...arr) // 错误

解决方法:在数组声明时加上 as const 将其变为只读元组:

function multiply(n: number, ...m: number[]) {
  return m.map((x) => n * x)
}
 
const arr = [1, 2, 3, 4] as const
const a = multiply(10, ...arr) // 正确

参数解构

function sum({ a, b, c }: { a: number; b: number; c: number }) {
  console.log(a + b + c)
}
 
// 或者:
type ABC = { a: number; b: number; c: number }
function sum({ a, b, c }: ABC) {
  console.log(a + b + c)
}

返回值

在参数列表之后添加返回类型注释

function myfunc(name: string, age: number): string {
  return `hello world, ${name}: ${age}`
}

void 类型

一般只用来表示函数没有返回值

函数的属性

函数也是对象,也可以有属性,定义函数的属性

type DescribableFunction = {
  description: string // 有一个属性名叫 description
  (someArg: number): boolean // 函数本身的定义
}
 
function doSomething(fn: DescribableFunction) {
  console.log(fn.description + " returned " + fn(6))
}
 
function myFunc(someArg: number) {
  return someArg > 3
}
myFunc.description = "default description"
 
doSomething(myFunc)

注意:和函数类型表达式的区别是,参数列表和返回的类型之间用的是 : 而不是 =>

函数重载

允许一个函数接受不同数量或类型的参数时,作出不同的处理

// 重载签名1
function makeDate(timestamp: number): Date
// 重载签名2
function makeDate(m: number, d: number, y: number): Date
 
// 实现签名
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
  if (d !== undefined && y !== undefined) {
    return new Date(y, mOrTimestamp, d)
  } else {
    return new Date(mOrTimestamp)
  }
}
 
// 下面都可以
const d1 = makeDate(12345678)
const d2 = makeDate(5, 5, 5)

重复多次定义函数,前几次都是函数定义(重载签名 overload signatures),最后一次是函数实现(实现签名 implementation signature)

构造函数

函数必须通过 new 操作符来调用,在前面加上 new 即可

type SomeConstructor = {
  new (s: string): SomeObject
}
 
let fn: SomeConstructor = class {
  s: string;
  constructor(s: string) {
    this.s = s
  }
}