如何让泛型Vector类的cross叉乘方法仅对3维向量实例暴露
实现方案
可以通过 TypeScript 条件类型拆分实例接口的方式,实现 cross 方法仅对3维向量可见,不需要单独定义子类:
// 定义所有维度通用的向量接口 interface BaseVector<N extends number> { dimensions: N values: number[] add(vector: Vector<N>): Vector<N> dot(vector: Vector<N>): number // 其他所有维度通用的方法、属性都在这里定义 } // 定义3维向量特有的方法扩展 interface Vector3D extends BaseVector<3> { cross(vector: Vector<3>): Vector<3> } // 条件类型:只有N为3时才返回带cross方法的类型,否则返回通用类型 export type Vector<N extends number> = N extends 3 ? Vector3D : BaseVector<N> // 内部实现类,所有维度的逻辑都在这里统一实现 class VectorImpl<N extends number> implements BaseVector<N> { constructor(public readonly dimensions: N, public values: number[]) {} add(vector: Vector<N>): Vector<N> { return new VectorImpl( this.dimensions, this.values.map((val, idx) => val + vector.values[idx]) ) as unknown as Vector<N> } dot(vector: Vector<N>): number { return this.values.reduce((sum, val, idx) => sum + val * vector.values[idx], 0) } // cross方法内部实现,非3维实例不会在类型层面暴露该方法 cross(vector: Vector<3>): Vector<3> { // 运行时防护,避免类型断言绕过类型检查的情况 if (this.dimensions !== 3) throw new Error('叉乘仅支持3维向量') const [x1, y1, z1] = this.values const [x2, y2, z2] = vector.values return new VectorImpl(3, [ y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2 ]) as unknown as Vector<3> } } // 导出构造器,也可以换成工厂函数 export const Vector = VectorImpl as new <N extends number>(dimensions: N, values: number[]) => Vector<N>
使用效果
- 3维向量实例可以正常看到并调用
cross方法,类型提示完全正常:
const v3_1 = new Vector(3, [1, 2, 3]) const v3_2 = new Vector(3, [4, 5, 6]) const crossRes = v3_1.cross(v3_2) // 类型正常,无报错
- 非3维向量实例在类型系统中完全不存在
cross方法,自动补全不会展示,强行调用会直接报「属性不存在」的类型错误:
const v2 = new Vector(2, [1, 2]) v2.cross() // 类型报错:类型“BaseVector<2>”上不存在属性“cross”
可选优化
如果不想单独拆分内部实现类,也可以直接通过类与同名接口合并+条件类型的方式实现,核心逻辑和上述方案一致,只是写法更紧凑。
内容的提问来源于stack exchange,提问作者Devoev
相关产品推荐
相关产品推荐

