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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:26:10