TypeScript:如何让farthest函数仅接受单一Origin类型,避免联合类型推断
解决TypeScript中farthest函数仅接受单一Origin类型坐标的问题
要实现farthest函数仅接受同一Origin类型的Coordinate参数,不同Origin类型传入时直接触发类型错误,我们需要阻止TypeScript将泛型参数推断为联合类型。以下是具体实现方案:
步骤1:定义联合类型检测辅助工具
首先需要两个辅助类型,用于判断泛型参数是否为联合类型:
// 将联合类型转换为交叉类型,用于检测是否为联合 type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // 判断类型是否为联合类型 type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
步骤2:修改farthest函数的类型定义
通过IsUnion约束泛型参数O,当O被推断为联合类型时,将参数列表的类型设为never,从而触发类型错误:
type Origin = "document" | "layout-viewport" | "visual-viewport"; interface Coordinate<O extends Origin> { x: number; y: number; } function farthest<O extends Origin>( ...coordinates: IsUnion<O> extends true ? never : Coordinate<O>[] ): Coordinate<O> { // 实现逻辑:计算距离原点最远的坐标 return coordinates.reduce((farthest, curr) => Math.hypot(farthest.x, farthest.y) >= Math.hypot(curr.x, curr.y) ? farthest : curr ); }
验证效果
测试不同场景的类型检查:
const c1: Coordinate<"layout-viewport"> = { x: 1, y: 1 }; const c2: Coordinate<"layout-viewport"> = { x: 1, y: 2 }; const c3: Coordinate<"document"> = { x: 1, y: 3 }; const f1 = farthest(c1, c2); // ✅ 正常,类型推断为 Coordinate<"layout-viewport"> const f2 = farthest(c1, c3); // ❌ 类型错误:类型"Coordinate<"document">"的参数不能赋给类型"never"的参数
可选优化:强制至少传入一个参数
如果希望函数必须接收至少一个坐标参数,可以调整函数定义,将第一个参数单独提取并绑定泛型:
function farthest<O extends Origin>( first: Coordinate<O>, ...rest: IsUnion<O> extends true ? never : Coordinate<O>[] ): Coordinate<O> { return [first, ...rest].reduce((farthest, curr) => Math.hypot(farthest.x, farthest.y) >= Math.hypot(curr.x, curr.y) ? farthest : curr ); }
这样既保证了参数数量的合理性,也严格限制了所有参数必须是同一Origin类型。
内容的提问来源于stack exchange,提问作者k-ui
相关产品推荐
相关产品推荐

