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

如何创建可接收值或Promise并返回同类型的TypeScript函数?

解决TypeScript中输入输出类型一致的函数定义问题

需求

创建一个TypeScript函数,满足:

  • 接收类型为A或Promise<A>的参数
  • 返回类型与输入完全匹配:输入A则返回A,输入Promise<A>则返回Promise<A>

问题分析

之前的尝试存在两个痛点:

  1. 使用泛型条件类型时,类型守卫分支中的参数类型变为T & Promise<A>或T,无法正确收窄到Promise<A>或A
  2. 使用联合类型参数A | Promise<A>时,类型守卫能正确识别分支类型,但无法标注正确的返回类型

解决方案

方案1:函数重载

函数重载能直接定义输入输出的对应关系,类型守卫也能正确收窄分支类型:

interface A {
  x(): void;
}

function isPromise<T>(obj: unknown): obj is Promise<T> {
  return typeof (obj as Promise<T>).then === "function";
}

const a: A = { x: () => {} };
const promiseA = Promise.resolve(a);

// 重载签名:定义输入输出的对应关系
function doSomething(arg: A): A;
function doSomething(arg: Promise<A>): Promise<A>;
// 实现签名:处理实际逻辑
function doSomething(arg: A | Promise<A>): A | Promise<A> {
  if (isPromise<A>(arg)) {
    const type: Promise<A> = arg; // 类型正确识别为Promise<A>
    return Promise.resolve(a);
  } else {
    const type: A = arg; // 类型正确识别为A
    return a;
  }
}

// 类型检查正常通过
const anA: A = doSomething(a);
const aPromiseA: Promise<A> = doSomething(promiseA);

// 以下两行会触发类型错误,符合预期
// const aPromiseB: Promise<A> = doSomething(a);
// const anB: A = doSomething(promiseA);

方案2:泛型条件类型优化

调整泛型约束,让TypeScript能正确推导返回类型,同时在分支中通过类型断言解决类型收窄问题:

interface A {
  x(): void;
}

function isPromise<T>(obj: unknown): obj is Promise<T> {
  return typeof (obj as Promise<T>).then === "function";
}

const a: A = { x: () => {} };
const promiseA = Promise.resolve(a);

function doSomething<T extends A | Promise<A>>(arg: T): T extends Promise<A> ? Promise<A> : A {
  if (isPromise<A>(arg)) {
    return Promise.resolve(a) as ReturnType<typeof doSomething<T>>;
  } else {
    return a as ReturnType<typeof doSomething<T>>;
  }
}

// 类型检查正常通过
const anA: A = doSomething(a);
const aPromiseA: Promise<A> = doSomething(promiseA);

// 以下两行会触发类型错误,符合预期
// const aPromiseB: Promise<A> = doSomething(a);
// const anB: A = doSomething(promiseA);

说明

  • 函数重载更直观,适合输入输出类型明确对应的场景,类型守卫在实现分支中能自动收窄类型
  • 泛型条件类型更灵活,适合需要复用类型逻辑的场景,但需要显式断言返回值类型,因为TypeScript无法自动推导泛型条件类型的分支返回值

内容的提问来源于stack exchange,提问作者Joseph Earl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:32:19