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

TypeScript强类型函数实现:将类映射为小写首字母键的实例对象

实现带强类型约束的TypeScript createObject函数,解决类名提取never问题

问题背景

需要实现一个createObject函数,接收多个类作为参数,返回的对象键为类名首字母小写形式,值为对应类的实例,且需具备完整的类型提示。当前函数无类型约束,同时尝试提取类名时得到never类型。

现有代码

function createObject (...classes: any[]) {
    return classes.reduce((acc, clazz) => {
        const name = clazz.name.charAt(0).toLowerCase() + clazz.name.slice(1);
        acc[name] = new clazz();
        return acc;
    }, {});
}

期望用法

const { aClass, bClass, cClass } = createObject(AClass, BClass, CClass);

类名提取失败代码

type GetName<T> = 'name' extends keyof T ? T['name'] : never;
type ClassName = GetName<AClass>; // 类型为never

问题原因

TypeScript默认会把类的name属性类型推断为string,而非具体的类名字面量(比如"AClass"),因此GetName<AClass>无法匹配到预期的字面量类型,最终返回never。

解决方案

1. 构建类名与实例的类型映射工具

先实现类型层面的类名提取、首字母小写转换,以及类到实例的映射:

// 定义可实例化的类构造函数类型,保留name属性的字面量类型
type ClassConstructor<T = any> = new (...args: any[]) => T & { constructor: { name: string } };

// 类型工具:将字符串首字母转为小写
type LowerFirst<T extends string> = T extends `${infer First}${infer Rest}` 
  ? `${Lowercase<First>}${Rest}` 
  : T;

// 类型工具:将类数组转换为「小写类名: 实例类型」的映射
type ClassInstanceMap<T extends ClassConstructor[]> = {
  [K in keyof T as T[K] extends ClassConstructor 
    ? LowerFirst<T[K]['constructor']['name']> 
    : never]: T[K] extends ClassConstructor<infer Instance> ? Instance : never;
};

2. 实现带强类型的createObject函数

结合上述类型工具,改造函数实现类型约束:

function createObject<T extends ClassConstructor[]>(...classes: [...T]): ClassInstanceMap<T> {
    return classes.reduce((acc, clazz) => {
        const name = clazz.name.charAt(0).toLowerCase() + clazz.name.slice(1) as LowerFirst<typeof clazz['name']>;
        acc[name] = new clazz();
        return acc;
    }, {} as ClassInstanceMap<T>);
}

3. 测试验证

定义测试类并使用函数:

class AClass {
    aProp = 'a';
}

class BClass {
    bProp = 'b';
}

// 使用函数,自动获得类型提示
const { aClass, bClass } = createObject(AClass, BClass);
console.log(aClass.aProp); // 类型提示正常,不会报错

关键说明

  • [...T]元组参数类型确保TypeScript能正确推断每个传入类的具体类型,而非合并为模糊的联合类型。
  • ClassInstanceMap通过映射类型,将每个类的类型转换为对应键值对,完全匹配运行时的键值逻辑。
  • 类型工具与运行时逻辑一一对应,保证类型提示和实际行为一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:02:49