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

如何将构造函数接口用作TypeScript泛型类型约束?

解决TypeScript泛型构造函数调用的编译错误

问题根源

TypeScript的泛型仅作用于编译阶段,运行时会被类型擦除。你代码里的T只是类型层面的标记,不是可执行的构造函数对象,所以直接写new T(contents)会触发'T' only refers to a type, but is being used as a value here错误。

修正方案

要复刻Swift中基于协议约束的模式,我们需要让DataStore在运行时能拿到实际的构造函数引用,同时保留类型安全约束:

  1. 明确StringDecodable接口的构造函数契约,匹配Swift中可抛出初始化器的语义
  2. 给DataStore添加构造参数,传入泛型类型的构造函数实例
  3. 在fetchResult中通过传入的构造函数创建实例,并处理可能的错误

完整可运行代码

1. 定义约束接口

// 匹配Swift中StringDecodable协议的语义:接收String参数的可抛出构造函数
interface StringDecodable {
  new (s: string): this;
}

2. 修正DataStore实现

class DataStore<T extends StringDecodable> {
  constructor(
    private readonly url: URL,
    // 新增参数:接收符合约束的构造函数
    private readonly decoder: new (s: string) => T
  ) {}

  async fetchResult(): Promise<T> {
    const response = await fetch(this.url);
    // 先处理HTTP请求错误
    if (!response.ok) {
      throw new Error(`请求失败,状态码: ${response.status}`);
    }
    const contents = await response.text();
    
    try {
      // 通过传入的decoder构造函数创建实例
      return new this.decoder(contents);
    } catch (err) {
      // 捕获构造函数抛出的解析错误
      throw new Error(`解析失败: ${(err as Error).message}`);
    }
  }
}

3. 实现符合约束的Time类

class Time implements StringDecodable {
  constructor(s: string) {
    // 模拟Swift中parseTheTimeString的解析逻辑,解析失败则抛出错误
    const timeParts = s.split(':');
    if (timeParts.length !== 2) {
      throw new Error('时间格式错误,需为HH:mm格式');
    }

    const hours = parseInt(timeParts[0], 10);
    const minutes = parseInt(timeParts[1], 10);

    if (isNaN(hours) || hours < 0 || hours > 23 || isNaN(minutes) || minutes < 0 || minutes > 59) {
      throw new Error('时间数值超出有效范围');
    }

    this.hours = hours;
    this.minutes = minutes;
  }

  readonly hours: number;
  readonly minutes: number;
}

4. 使用示例

async function run() {
  try {
    const timeUrl = new URL('https://whattimeisit.org/');
    // 传入Time构造函数给DataStore
    const timeStore = new DataStore<Time>(timeUrl, Time);
    const currentTime = await timeStore.fetchResult();
    console.log(`当前时间:${currentTime.hours}:${currentTime.minutes}`);
  } catch (error) {
    console.error('处理失败:', (error as Error).message);
  }
}

run();

关键说明

  • 通过将构造函数decoder作为参数传入DataStore,解决了TypeScript泛型类型擦除导致的无法调用构造函数问题
  • 保留了类型约束,确保只有符合StringDecodable接口的类型才能被DataStore使用
  • 新增了HTTP请求错误和解析错误的处理,贴合Swift中throws的错误处理语义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:40:37