Skip to main content

Function Type

Function Interface

interface ReturnString {
(): string
}

declare const foo: ReturnString

const bar = foo() // bar 被推断为一个字符串
interface Complex {
(foo: string, bar?: number, ...others: boolean[]): number
}
interface Overloaded {
(foo: string): string
(foo: number): number
}

// 实现接口的一个例子:
function stringOrNumber(foo: number): number
function stringOrNumber(foo: string): string
function stringOrNumber(foo: any): any {
if (typeof foo === 'number')
return foo * foo
else if (typeof foo === 'string')
return `hello ${foo}`
}

const overloaded: Overloaded = stringOrNumber

// 使用
const str = overloaded('') // str 被推断为 'string'
const num = overloaded(123) // num 被推断为 'number'

WangCai extends Dog extends Animal. Animal => WangCai 是 Dog => Dog 的子类型:

  • 函数参数的类型兼容是反向的, 称之为逆变.
  • 返回值的类型兼容是正向的, 称之为协变.

Arrow Function

在一个以 number 类型为参数,以 string 类型为返回值的函数中:

const simple: (foo: number) => string = foo => foo.toString()

Function Overload

函数签名的类型重载:

  • 多个重载签名和一个实现签名.
  • 定义了重载签名, 则实现签名对外不可见.
  • 实现签名必须兼容重载签名.
// 重载
function padding(all: number)
function padding(topAndBottom: number, leftAndRight: number)
function padding(top: number, right: number, bottom: number, left: number)
function padding(a: number, b?: number, c?: number, d?: number) {
if (b === undefined && c === undefined && d === undefined) {
b = c = d = a
} else if (c === undefined && d === undefined) {
c = a
d = b
}
return {
top: a,
right: b,
bottom: c,
left: d,
}
}

padding(1) // Okay: all
padding(1, 1) // Okay: topAndBottom, leftAndRight
padding(1, 1, 1, 1) // Okay: top, right, bottom, left
padding(1, 1, 1) // Error: Not a part of the available overloads
Function Overload

TypeScript 中的函数重载没有任何运行时开销. 它只允许你记录希望调用函数的方式, 并且编译器会检查其余代码.

Rest Parameters

type Arr = readonly unknown[]
function partialCall<T extends Arr, U extends Arr, R>(
f: (...args: [...T, ...U]) => R,
...headArgs: T
) {
return (...tailArgs: U) => f(...headArgs, ...tailArgs)
}

function foo(x: string, y: number, z: boolean) {}
const f1 = partialCall(foo, 100)
const f2 = partialCall(foo, 'hello', 100, true, 'oops')
const f3 = partialCall(foo, 'hello')

f3(123, true)
f3()
f3(123, 'hello')

Function Types Design

  • Input types tend to be broader than output types.
  • Optional properties and union types are more common in parameter types.
  • To reuse types between parameters and return types, introduce a canonical form (for return types) and a looser form (for parameters).
interface LngLat {
lng: number
lat: number
}

type LngLatLike = LngLat | { lon: number, lat: number } | [number, number]

interface Camera {
center: LngLat
zoom: number
bearing: number
pitch: number
}

interface CameraOptions extends Omit<Partial<Camera>, 'center'> {
center?: LngLatLike
}

function createCamera(options: CameraOptions): Camera {
return CameraFactory.create(options)
}