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

如何在TypeScript的Record类型对象中自动实现类型收窄?

TypeScript 联合类型收窄与对象方法类型匹配问题

问题代码

enum ResourceType {
  A = 'a',
  B = 'b',
}

export type Resource = ResourceA | ResourceB

export type ResourceA = {
  type: ResourceType.A
  name: "A"
}

export type ResourceB = {
  type: ResourceType.B,
  name: "B"
}

const elements: Record<
  ResourceType,
  (resource: Resource) => void
> = {
  a: (resource: ResourceA) => (
    console.log(resource)
  ),
  b: (resource: ResourceB) => (
    console.log(resource)
  )
}

TypeScript 提示错误:Type '(resource: ResourceA) => void' is not assignable to type '(resource: Resource) => void',这是预期情况。

需求:希望根据与resource.type匹配的对象键自动收窄方法参数的类型,但一直未能实现。


解决方案

方法一:手动映射类型关联

先定义映射类型绑定ResourceType枚举值与对应Resource子类型,再用映射类型约束elements对象:

enum ResourceType {
  A = 'a',
  B = 'b',
}

export type ResourceA = {
  type: ResourceType.A
  name: "A"
}

export type ResourceB = {
  type: ResourceType.B,
  name: "B"
}

export type Resource = ResourceA | ResourceB

// 建立枚举与子类型的映射关系
type ResourceMap = {
  [ResourceType.A]: ResourceA
  [ResourceType.B]: ResourceB
}

// 用映射类型定义elements的类型,自动匹配参数类型
const elements: {
  [K in ResourceType]: (resource: ResourceMap[K]) => void
} = {
  a: (resource) => {
    console.log(resource) // 参数自动收窄为ResourceA
  },
  b: (resource) => {
    console.log(resource) // 参数自动收窄为ResourceB
  }
}

方法二:用Extract自动提取子类型

利用TypeScript内置的Extract类型,从联合类型中自动提取对应type的子类型,无需手动维护映射关系:

enum ResourceType {
  A = 'a',
  B = 'b',
}

export type ResourceA = {
  type: ResourceType.A
  name: "A"
}

export type ResourceB = {
  type: ResourceType.B,
  name: "B"
}

export type Resource = ResourceA | ResourceB

// 从联合类型中提取指定type的子类型
type ResourceOfType<T extends ResourceType> = Extract<Resource, { type: T }>

// 动态生成elements的类型约束
const elements: {
  [K in ResourceType]: (resource: ResourceOfType<K>) => void
} = {
  a: (resource) => console.log(resource), // 参数为ResourceA
  b: (resource) => console.log(resource), // 参数为ResourceB
}

这两种方式都能实现根据对象键自动收窄方法参数的类型,同时保证类型安全,后续新增Resource子类型时,只需扩展枚举和联合类型即可自动适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:54:19