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

TypeScript如何定义键为联合类型、值类型各异的对象类型

问题描述

需要创建一个对象类型,满足两个约束:

  • 所有键必须属于给定的字符串字面量联合类型,由编译器强制校验,不能多也不能少
  • 每个键对应的值类型独立,和键本身绑定

具体场景:有一组PluginId字符串字面量联合类型代表不同插件,需要定义插件配置对象类型,键必须是PluginId的成员,每个键对应的值是该插件专属的配置类型。

初始实现代码:

// 插件ID字面量联合类型
export type PluginId = 'cat' | 'dog' | 'racoon'

/**
 * 配置值规则:
 * - false 表示插件关闭
 * - true 表示插件启用,使用默认配置
 * - 传入自定义配置对象表示插件启用,使用自定义配置
 */
export type Config<T = {}> = boolean | Partial<T>

// 各插件专属配置类型,无专属配置的插件不需要定义
export type DogPluginConfig = { woof: boolean }
export type CatPluginConfig = { meow: boolean }

// 目标配置类型
export type Configs = {
  cat?: Config<CatPluginConfig>
  dog?: Config<DogPluginConfig>
  racoon?: Config
}

export function instantiatePlugins(configs: Configs): Plugin[] {
  // 业务逻辑省略
}

上述实现的缺陷是Configs和PluginId之间没有强制绑定:修改PluginId的成员时,编译器不会提示Configs是否漏写/多写了键,也无法阻止给Configs对象添加不属于PluginId的非法键。

尝试过的Record交叉类型方案:

export type Configs = Partial<Record<PluginId, Config>> & {
  cat?: Config<CatPluginConfig>
  dog?: Config<DogPluginConfig>
}

该方案依然存在缺陷:交叉类型不会校验后半段对象的键范围,既允许写入不在PluginId中的多余键,也不会在PluginId新增成员时提示缺失对应配置项。


解决方案

使用TS的映射类型即可完美满足需求,实现逻辑如下:

  1. 首先定义插件ID到专属配置类型的映射表,覆盖所有PluginId成员
  2. 通过映射类型遍历PluginId联合类型,自动生成每个键对应的配置类型,从根源上保证键的合法性

基础实现

// 插件ID与专属配置的映射表,无专属配置的插件对应默认空对象类型
type PluginConfigMap = {
  cat: CatPluginConfig
  dog: DogPluginConfig
  racoon: {}
}

// 生成最终配置类型:键全部来自PluginId,每个键匹配对应专属Config类型,所有键可选
export type Configs = {
  [K in PluginId]?: Config<PluginConfigMap[K]>
}

该实现自动满足所有约束:

  • 无法添加PluginId以外的键,编译器会直接报错
  • 每个键的值类型自动匹配对应插件的配置类型,编写自定义配置时会获得正确的类型提示
  • 修改PluginId成员时,编译器会提示PluginConfigMap是否存在漏写的键

强化校验(可选)

如果需要强制PluginConfigMap和PluginId完全同步(既不能漏写键,也不能多写键),可以加一层泛型校验工具:

// 校验传入的类型必须包含所有PluginId的键,且不能有多余键
type ExactConfigMap<T extends Record<PluginId, unknown>> = {
  [K in keyof T]: K extends PluginId ? T[K] : never
}

// 用校验工具包裹映射表,一旦键和PluginId不匹配会直接抛出类型错误
type PluginConfigMap = ExactConfigMap<{
  cat: CatPluginConfig
  dog: DogPluginConfig
  racoon: {}
  // 多写bird: {} 或者漏写racoon都会直接报类型错误
}>

内容的提问来源于stack exchange,提问作者Balázs Édes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:48:45