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

如何通过字符串类型引用对象类型并指定泛型参数?

TypeScript 通过字符串泛型匹配对应 RigidbodyShape 类型

问题场景

我在RigidbodyShape中定义了两种对象类型的联合类型:

export type RigidbodyShape = { type: 'sphere', radius: number; } |
{ type: 'cube', size: { width: number, height: number, depth: number; }; }

我希望通过向类的泛型传入'cube'、'sphere'这类字符串字面量,直接获取对应的类型结构。现有代码存在类型关联错误,需要调整:

export interface RigidbodyOptions {
  shape: RigidbodyShape<T>;
}

class MyClass {
  constructor() {
    public readonly rigidbody: RigidbodyRef<'cube'>
  }
}

export class RigidbodyRef<T> {
  options!: T;
}

解决方案

核心思路是通过条件类型或Extract工具类型从联合类型中筛选出对应type字段的成员,再通过泛型将字符串字面量与目标类型绑定。

步骤1:定义类型提取工具(二选一)

如果你不想修改原有的RigidbodyShape,可以用Extract工具类型快速提取对应类型:

// 提取指定 type 对应的 RigidbodyShape 成员
export type RigidbodyShapeByType<T extends 'sphere' | 'cube'> = Extract<RigidbodyShape, { type: T }>;

或者直接给RigidbodyShape添加泛型参数,让它支持直接传入类型字符串:

// 直接让 RigidbodyShape 接受泛型参数,默认返回所有类型的联合
export type RigidbodyShape<T extends 'sphere' | 'cube' = 'sphere' | 'cube'> = 
  T extends 'sphere' ? { type: 'sphere', radius: number; } :
  T extends 'cube' ? { type: 'cube', size: { width: number, height: number, depth: number; }; } :
  never;

步骤2:修正RigidbodyOptions的泛型关联

让RigidbodyOptions接受泛型参数,关联到提取出的目标类型:

// 使用 Extract 方案的写法
export interface RigidbodyOptions<T extends 'sphere' | 'cube'> {
  shape: RigidbodyShapeByType<T>;
}

// 或者使用泛型 RigidbodyShape 的写法
export interface RigidbodyOptions<T extends 'sphere' | 'cube'> {
  shape: RigidbodyShape<T>;
}

步骤3:调整RigidbodyRef的泛型逻辑

让RigidbodyRef的泛型约束为合法的类型字符串,同时将options类型绑定到RigidbodyOptions:

export class RigidbodyRef<T extends 'sphere' | 'cube'> {
  options!: RigidbodyOptions<T>;
}

步骤4:修正MyClass的代码(修复语法错误+类型关联)

原代码中public修饰符位置错误,需要放在属性定义上,同时完成实例化:

class MyClass {
  public readonly rigidbody: RigidbodyRef<'cube'>;

  constructor() {
    this.rigidbody = new RigidbodyRef<'cube'>();
    // 此时 TypeScript 会自动提示 shape 的 size 属性,类型校验生效
    this.rigidbody.options.shape.size.width = 10;
  }
}

优化:统一维护类型字符串

为了避免重复写'sphere' | 'cube',可以提取成单独的类型别名:

export type RigidbodyType = 'sphere' | 'cube';

// 后续所有泛型约束都替换为 RigidbodyType
export type RigidbodyShapeByType<T extends RigidbodyType> = Extract<RigidbodyShape, { type: T }>;
export interface RigidbodyOptions<T extends RigidbodyType> {
  shape: RigidbodyShapeByType<T>;
}
export class RigidbodyRef<T extends RigidbodyType> {
  options!: RigidbodyOptions<T>;
}

内容的提问来源于stack exchange,提问作者Get Off My Lawn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:36:14