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

TypeScript实现无限柯里化joinPath,如何返回字面量类型?

为无限柯里化路径拼接函数实现字面量类型返回

原始问题代码

你当前实现的joinPath函数通过无限柯里化拼接路径,但返回类型仅为string,无法保留具体的路径字面量类型:

function joinPath(): string
function joinPath(a: string): typeof joinPath
function joinPath(a?: string): string | typeof joinPath {
  if (a === undefined) { return '' }
  const func = (b?: string) => {
    if (b === undefined) { return a }
    return joinPath(`${a}/${b}`)
  }

  return func as typeof joinPath
}

// 类型为 string,而非 'www.github.com'
console.log(joinPath('www.github.com')())
// 最终调用类型为 string,而非 'www.github.com/react'
console.log(joinPath('www.github.com')('react')())

解决方案:用递归泛型追踪字面量类型

要实现字面量类型的推导,需要定义递归的泛型函数类型,来追踪每一步拼接后的路径字面量:

1. 定义递归柯里化类型

// 递归类型:累积路径为 T,无参调用返回 T,传参则拼接新路径并返回新的柯里化函数
type JoinPathFn<T extends string = ''> = {
  (): T;
  <U extends string>(path: U): JoinPathFn<T extends '' ? U : `${T}/${U}`>;
};

2. 实现带泛型的柯里化函数

function joinPath(): '';
function joinPath<T extends string>(path: T): JoinPathFn<T>;
function joinPath<T extends string>(path?: T): '' | JoinPathFn<T> {
  if (path === undefined) {
    return '';
  }

  // 内部函数处理拼接逻辑,通过类型断言匹配泛型类型
  const curriedFn = ((nextPath?: string) => {
    if (nextPath === undefined) {
      return path;
    }
    return joinPath(`${path}/${nextPath}`);
  }) as unknown as JoinPathFn<T>;

  return curriedFn;
}

3. 测试类型推导

// 类型为 'www.github.com'(字面量类型)
const path1 = joinPath('www.github.com')();
// 类型为 'www.github.com/react'(字面量类型)
const path2 = joinPath('www.github.com')('react')();
// 类型为 'a/b/c/d'(字面量类型)
const path3 = joinPath('a')('b')('c')('d')();
// 类型为 ''(空字符串字面量)
const emptyPath = joinPath();

原理说明

  • JoinPathFn<T>是递归泛型类型,每次传入新路径时,会通过模板字符串类型${T}/${U}拼接出精确的路径字面量,并返回新的柯里化函数类型。
  • 函数重载明确了不同调用场景的返回类型:无参调用返回空字符串字面量'',传入路径时返回对应累积路径的柯里化函数。
  • 内部函数通过类型断言匹配泛型类型,确保TypeScript能正确推导每一步的字面量类型。

内容的提问来源于stack exchange,提问作者USUNG YANG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:50:29