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

TypeScript如何基于构造函数参数自动推导条件泛型类型?

TypeScript泛型类自动推导泛型类型的实现方案

问题场景

你定义了如下Collection类:

// 补充代码中缺失的类型定义
type ObjectWithNumberId = { id: number; [key: string]: any };

class Collection<ID extends string | number> {
    // 原代码类型错误,entries应为带id的对象数组而非ID[]
    entries: { id: ID }[];

    constructor(private readonly useStringIds: boolean) {}

    getIds(): ID[] {
        // 原代码遗漏this,修正为this.entries
        return this.entries.map((entry) => entry.id);
    }

    handleResults(results: ObjectWithNumberId[]) {
        if (this.useStringIds) {
            this.entries = results.map((result) => ({
                ...result,
                id: result.id.toString(),
            }));
        } else {
            this.entries = results;
        }        
    }
}

当前使用时必须同时指定泛型类型和构造函数参数(如const c = new Collection<string>(true);),希望仅传入构造函数参数,让TypeScript自动推导对应的泛型类型。

解决方案

TypeScript无法直接从构造函数的boolean参数推导类的泛型,但可以通过静态工厂方法实现自动推导。利用静态方法的参数字面量类型,让TS根据传入的useStringIds值自动推断返回实例的泛型类型:

修改后的完整代码

type ObjectWithNumberId = { id: number; [key: string]: any };

class Collection<ID extends string | number> {
    entries: { id: ID }[];

    // 将构造函数设为private,强制通过工厂方法创建实例
    private constructor(private readonly useStringIds: boolean) {}

    getIds(): ID[] {
        return this.entries.map((entry) => entry.id);
    }

    handleResults(results: ObjectWithNumberId[]) {
        if (this.useStringIds) {
            this.entries = results.map((result) => ({
                ...result,
                id: result.id.toString(),
            })) as { id: ID }[];
        } else {
            this.entries = results as { id: ID }[];
        }        
    }

    // 静态工厂方法,根据参数类型自动推导泛型
    static create<T extends boolean>(useStringIds: T): Collection<T extends true ? string : number> {
        return new Collection(useStringIds);
    }
}

使用示例

// 自动推导为Collection<string>
const stringCollection = Collection.create(true);
stringCollection.handleResults([{ id: 1, name: "test" }]);
const stringIds = stringCollection.getIds(); // 类型为string[]

// 自动推导为Collection<number>
const numberCollection = Collection.create(false);
numberCollection.handleResults([{ id: 2, name: "demo" }]);
const numberIds = numberCollection.getIds(); // 类型为number[]

说明

  1. 将构造函数设为private,避免直接通过new创建实例,强制使用工厂方法保证类型推导的正确性。
  2. 静态工厂方法create的参数使用字面量类型T extends boolean,通过条件类型T extends true ? string : number将参数值映射为对应的泛型类型。
  3. 修正了原代码中entries类型定义错误、getIds方法遗漏this的问题,确保类型逻辑自洽。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 22:52:23