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

TypeScript如何通过类映射获取实例类型而非构造函数类型?

解决TypeScript中从类映射获取实例类型的问题

问题分析

你当前的ClassMap类型存储的是类的构造函数类型(typeof Foo、typeof Bar),而不是类的实例类型(Foo、Bar),所以直接访问val属性会报错——因为构造函数本身没有val属性,val是实例的属性。

解决方案

TypeScript提供了内置工具类型InstanceType,可以从构造函数类型中提取对应的实例类型。下面提供两种常用的处理方式:

方式1:直接针对单个类型转换

如果只需要获取某一个键对应的实例类型,可以直接用InstanceType包裹构造函数类型:

class Foo {
  constructor(public val: number) {}
}

class Bar {
  constructor(public val: string) {}
}

const classMap = {
  foo: Foo,
  bar: Bar,
} as const;

type ClassMap = typeof classMap;
// 直接转换为实例类型
type InferredFoo = InstanceType<ClassMap["foo"]>; // Foo
type ShouldBeNumber = InferredFoo["val"]; // number,无报错

方式2:创建完整的实例类型映射

如果需要把整个ClassMap转换成实例类型的映射,可以自定义一个映射类型,结合InstanceType和条件类型处理(支持混合非类属性的场景):

class Foo {
  constructor(public val: number) {}
}

class Bar {
  constructor(public val: string) {}
}

const classMap = {
  foo: Foo,
  bar: Bar,
  baz: 10,
} as const;

type ClassMap = typeof classMap;

// 自定义映射类型:将构造函数类型转为实例类型,非构造函数类型保持原样
type InstanceMap<T> = {
  [K in keyof T]: T[K] extends new (...args: any[]) => infer R ? R : T[K]
};

type ClassInstanceMap = InstanceMap<ClassMap>;
// { readonly foo: Foo, readonly bar: Bar, readonly baz: 10 }

type InferredFoo = ClassInstanceMap["foo"]; // Foo
type ShouldBeNumber = InferredFoo["val"]; // number
type BazType = ClassInstanceMap["baz"]; // 10

说明

  • InstanceType<ConstructorType>是TypeScript内置工具类型,专门用于从构造函数类型中提取实例类型,完全是编译时操作,不会影响运行时代码。
  • 自定义的InstanceMap类型通过条件类型判断属性是否为构造函数,兼容混合了类和其他类型值的映射场景,保持非类属性的类型不变。

内容的提问来源于stack exchange,提问作者Adam B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:18:13