You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中定义绑定联合类型成员的函数类型?

TypeScript类型定义:绑定values数组与renderer函数类型并支持联合类型

问题场景

现有代码尝试将values数组与renderer函数的类型绑定,但TypeScript报错提示number无法赋值给string,原代码如下:

interface MyObject {
  select: SelectData<string | number>
}

interface SelectData<T extends string | number> {
  values: T[]
  renderer: (values: T[]) => string
}

// 报错:renderer的参数类型number[]无法匹配(string | number)[]
const obj: MyObject = {
  select: {
    values: [1, 2],
    renderer: (values: number[]) => 'sth'
  }
}

const obj2: MyObject2 = {
  select: {
    values: ['one', 'two'],
    renderer: (values: string[]) => 'sth'
  }
}

需求:

  1. 当values为某一类型时,renderer仅接受该类型的数组作为参数;
  2. 支持多种可接受的类型,理想情况下通过联合类型定义。

解决方案

核心问题在于原定义中SelectData<string | number>会让values和renderer的参数都变成(string | number)[],但你需要的是**values和renderer参数类型严格一致的独立类型的联合**,而非一个同时兼容两种类型的单一类型。

方案一:直接使用联合类型

将MyObject的select属性定义为SelectData<string> | SelectData<number>,这样TypeScript会自动识别每个子类型的结构,确保values和renderer的类型绑定:

interface SelectData<T extends string | number> {
  values: T[]
  renderer: (values: T[]) => string
}

interface MyObject {
  select: SelectData<string> | SelectData<number>
}

// 正常通过类型检查
const obj: MyObject = {
  select: {
    values: [1, 2],
    renderer: (values: number[]) => 'sth'
  }
}

// 正常通过类型检查
const obj2: MyObject = {
  select: {
    values: ['one', 'two'],
    renderer: (values: string[]) => 'sth'
  }
}

// 报错:values是string[]但renderer接受number[],类型不匹配
const invalidObj: MyObject = {
  select: {
    values: ['one', 'two'],
    renderer: (values: number[]) => 'sth'
  }
}

方案二:自动生成联合类型(适用于扩展更多类型的场景)

如果需要支持更多类型(比如boolean),可以用分发式条件类型自动生成所有子类型的SelectData联合,避免手动枚举:

interface SelectData<T extends string | number | boolean> {
  values: T[]
  renderer: (values: T[]) => string
}

// 分发式条件类型:将联合类型T拆分为每个子类型的SelectData联合
type SelectDataUnion<T> = T extends string | number | boolean ? SelectData<T> : never

interface MyObject {
  select: SelectDataUnion<string | number | boolean>
}

// 正常通过类型检查
const boolObj: MyObject = {
  select: {
    values: [true, false],
    renderer: (values: boolean[]) => 'bool'
  }
}

原理说明

当你使用SelectData<string> | SelectData<number>时,TypeScript会进行联合类型的判别:

  • 对于{ values: number[], renderer: (number[]) => string },它匹配SelectData<number>;
  • 对于{ values: string[], renderer: (string[]) => string },它匹配SelectData<string>;
  • 任何values和renderer类型不匹配的结构都会被TypeScript拦截,满足你的类型绑定需求。

而原定义中SelectData<string | number>会让renderer的参数要求是(string | number)[],但(number[]) => string不能赋值给((string | number)[]) => string(函数参数是逆变位置,更窄的类型不能赋值给更宽的类型),这就是报错的原因。

内容的提问来源于stack exchange,提问作者Faire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:05:22