如何通过字符串类型引用对象类型并指定泛型参数?
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
相关产品推荐
相关产品推荐

