函数类型定义了函数的参数类型和返回值类型。在 TypeScript 中,函数类型是一等公民,可以作为变量的类型、参数的类型或返回值的类型。
函数类型使用箭头语法 (参数列表) => 返回值类型 来定义。
type AddFunction = (a: number, b: number) => number
const add: AddFunction = (a, b) => {
return a + b
}
console.log(add(10, 20))
AddFunction 描述了一个接受两个数字参数并返回数字的函数。变量 add 被标注为这个类型后,TypeScript 会自动推断参数 a 和 b 的类型。
使用 type 关键字可以给函数类型起别名,让代码更加清晰。
type Callback = (data: string) => void
type Validator = (value: unknown) => boolean
type Comparer<T> = (a: T, b: T) => number
const logCallback: Callback = (data) => {
console.log(data)
}
const isString: Validator = (value) => {
return typeof value === "string"
}
const numberComparer: Comparer<number> = (a, b) => {
return a - b
}
logCallback("测试消息")
console.log(isString("hello"))
console.log([3, 1, 2].sort(numberComparer))
类型别名让复杂的函数类型变得易于理解和复用。
接口也可以定义函数类型,使用调用签名语法。
interface SearchFunction {
(source: string, pattern: string): boolean
}
const contains: SearchFunction = (source, pattern) => {
return source.includes(pattern)
}
console.log(contains("hello world", "world"))
console.log(contains("hello world", "foo"))
接口定义的函数类型可以扩展,适合需要添加属性的函数对象。
构造签名描述可以用 new 调用的函数,即构造函数。
interface Constructor {
new (name: string): { name: string }
}
function createInstance(ctor: Constructor, name: string) {
return new ctor(name)
}
class Person {
constructor(public name: string) {}
}
const person = createInstance(Person, "张三")
console.log(person.name)
构造签名常用于工厂函数和依赖注入场景。
TypeScript 可以根据上下文推断函数参数的类型。
const numbers = [1, 2, 3, 4, 5]
const doubled = numbers.map((n) => n * 2)
const evens = numbers.filter((n) => n % 2 === 0)
const sum = numbers.reduce((acc, n) => acc + n, 0)
console.log(doubled)
console.log(evens)
console.log(sum)
回调函数的参数类型会根据数组的类型自动推断,不需要显式标注。
函数类型可以作为其他函数的参数类型,实现高阶函数。
type Transform<T> = (value: T) => T
function processArray<T>(arr: T[], transform: Transform<T>): T[] {
return arr.map(transform)
}
const numbers = [1, 2, 3, 4, 5]
const squared = processArray(numbers, (n) => n * n)
console.log(squared)
Transform 类型描述了一个转换函数,processArray 接受这个类型的函数作为参数。
函数可以返回另一个函数,返回的函数也有明确的类型。
type Multiplier = (x: number) => number
function createMultiplier(factor: number): Multiplier {
return (x) => x * factor
}
const double = createMultiplier(2)
const triple = createMultiplier(3)
console.log(double(5))
console.log(triple(5))
createMultiplier 返回一个 Multiplier 类型的函数,这个函数会记住创建时的 factor 值。
函数类型也可以定义重载,描述多种调用方式。
type StringOrNumber = {
(value: string): string
(value: number): number
}
const identity: StringOrNumber = (value: any) => value
console.log(identity("hello"))
console.log(identity(123))
重载类型描述了函数的不同调用签名,实现时需要处理所有情况。
有些函数既可以作为普通函数调用,也可以作为构造函数调用。
interface DateConstructor {
new (value: number): Date
(value: number): string
}
function useDate(ctor: DateConstructor) {
const instance = new ctor(1234567890000)
const result = ctor(1234567890000)
return { instance, result }
}
这种类型同时包含调用签名和构造签名,描述了像 Date 这样的内置对象。
函数类型在实际开发中常用于定义回调函数和事件处理器。
type RequestCallback = (error: Error | null, data?: any) => void
function fetchData(url: string, callback: RequestCallback): void {
setTimeout(() => {
if (url.includes("error")) {
callback(new Error("请求失败"))
} else {
callback(null, { message: "成功" })
}
}, 1000)
}
fetchData("https://api.example.com/data", (error, data) => {
if (error) {
console.error(error.message)
} else {
console.log(data)
}
})
RequestCallback 定义了标准的 Node.js 风格回调函数类型。
函数类型是 TypeScript 类型系统的核心组成部分。通过函数类型,我们可以精确描述函数的输入和输出,实现类型安全的高阶函数。函数类型别名让复杂类型变得易于理解,接口定义的函数类型可以扩展和组合。掌握函数类型是编写可复用、类型安全代码的关键。