函数类型接口

接口可以定义函数的类型签名,用于描述函数的参数和返回值类型。

基本语法

interface GreetFunction {
  (name: string): string
}

const greet: GreetFunction = (name) => {
  return `你好,${name}`
}

console.log(greet("张三"))  // "你好,张三"

函数参数

interface MathOperation {
  (a: number, b: number): number
}

const add: MathOperation = (a, b) => a + b
const subtract: MathOperation = (a, b) => a - b
const multiply: MathOperation = (a, b) => a * b

console.log(add(10, 5))      // 15
console.log(subtract(10, 5)) // 5
console.log(multiply(10, 5)) // 50

回调函数类型

interface Callback {
  (data: string): void
}

function fetchData(url: string, callback: Callback): void {
  setTimeout(() => {
    callback("数据加载完成")
  }, 1000)
}

fetchData("/api/data", (data) => {
  console.log(data)
})

可调用签名

对象可以同时具有属性和方法:

interface Counter {
  (): number
  count: number
  increment(): void
}

function createCounter(): Counter {
  const counter = function() {
    return counter.count
  } as Counter

  counter.count = 0
  counter.increment = function() {
    this.count++
  }

  return counter
}

const counter = createCounter()
counter.increment()
console.log(counter())  // 1

构造签名

使用 new 关键字定义构造函数类型:

interface Constructor {
  new (name: string): User
}

interface User {
  name: string
  greet(): string
}

class Person implements User {
  constructor(public name: string) {}
  greet() {
    return `你好,${this.name}`
  }
}

function createUser(ctor: Constructor, name: string): User {
  return new ctor(name)
}

const user = createUser(Person, "张三")
console.log(user.greet())  // "你好,张三"

实际应用

事件处理器

interface EventHandler {
  (event: Event): void
}

interface EventEmitter {
  on(event: string, handler: EventHandler): void
  emit(event: string, data: any): void
}

class SimpleEmitter implements EventEmitter {
  private handlers: Map<string, EventHandler[]> = new Map()

  on(event: string, handler: EventHandler): void {
    if (!this.handlers.has(event)) {
      this.handlers.set(event, [])
    }
    this.handlers.get(event)!.push(handler)
  }

  emit(event: string, data: any): void {
    const handlers = this.handlers.get(event) || []
    handlers.forEach(handler => handler(data))
  }
}

策略模式

interface SortStrategy {
  (a: number, b: number): number
}

const ascending: SortStrategy = (a, b) => a - b
const descending: SortStrategy = (a, b) => b - a

function sortNumbers(numbers: number[], strategy: SortStrategy): number[] {
  return [...numbers].sort(strategy)
}

const numbers = [3, 1, 4, 1, 5, 9]

console.log(sortNumbers(numbers, ascending))   // [1, 1, 3, 4, 5, 9]
console.log(sortNumbers(numbers, descending))  // [9, 5, 4, 3, 1, 1]

过滤器

interface Filter<T> {
  (item: T): boolean
}

function filterArray<T>(array: T[], filter: Filter<T>): T[] {
  return array.filter(filter)
}

const numbers = [1, 2, 3, 4, 5, 6]

const isEven: Filter<number> = (n) => n % 2 === 0
const isGreaterThanThree: Filter<number> = (n) => n > 3

console.log(filterArray(numbers, isEven))             // [2, 4, 6]
console.log(filterArray(numbers, isGreaterThanThree)) // [4, 5, 6]

转换器

interface Transformer<T, U> {
  (input: T): U
}

function mapArray<T, U>(array: T[], transformer: Transformer<T, U>): U[] {
  return array.map(transformer)
}

const strings = ["1", "2", "3"]

const toNumber: Transformer<string, number> = (s) => parseInt(s, 10)
const toLength: Transformer<string, number> = (s) => s.length

console.log(mapArray(strings, toNumber))  // [1, 2, 3]
console.log(mapArray(strings, toLength))  // [1, 1, 1]

函数重载

interface StringOrNumber {
  (value: string): string
  (value: number): number
}

const process: StringOrNumber = (value: string | number) => {
  if (typeof value === "string") {
    return value.toUpperCase()
  }
  return value * 2
}

console.log(process("hello"))  // "HELLO"
console.log(process(5))        // 10

注意事项

与类型别名的区别

// 接口
interface Greet {
  (name: string): string
}

// 类型别名
type GreetType = (name: string) => string

两者功能相同,但接口可以扩展。

参数名称

接口中的参数名称只是文档作用:

interface Add {
  (a: number, b: number): number
}

const add: Add = (x, y) => x + y  // 参数名可以不同

可选参数

interface Greet {
  (name: string, greeting?: string): string
}

const greet: Greet = (name, greeting = "你好") => {
  return `${greeting}${name}`
}

console.log(greet("张三"))           // "你好,张三"
console.log(greet("张三", "早上好")) // "早上好,张三"