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

TypeScript:类型收窄后如何正确推断函数返回类型?

TypeScript 根据调用上下文精准推断函数返回类型的解决方案

我希望TypeScript能依据函数的调用上下文,正确推断其返回类型。当前TS会将结果推断为联合类型'isA' | 'isB',但我期望在通过条件语句收窄输入类型后,返回类型也能随之对应收窄。

三种实现方案

  • 朴素方案:

    function matchType1<A, B>(
      type: "a" | "b",
      fns: { onA: () => A; onB: () => B }
    ) {
      return type === "a" ? fns.onA() : fns.onB()
    }
    
  • 对象包装方案:

    function matchType2<A, B>(
      type: "a" | "b",
      fns: { onA: () => A; onB: () => B}
    ) {
      return type === "a" 
        ? { a: fns.onA() }
        : { b: fns.onB() }
    }
    
  • 重载函数方案:

    function matchType3<A, B>(type: "a", fns: { onA: () => A; onB: () => B }): A;
    function matchType3<A, B>(type: "b", fns: { onA: () => A; onB: () => B }): B;
    function matchType3<A, B>(
      type: "a" | "b",
      fns: { onA: () => A; onB: () => B }
    ) {
      return type === "a" ? fns.onA() : fns.onB();
    }
    

使用示例

async function main(type: "a" | "b") {
  const promise1 = matchType1(type, {
    onA: () => Promise.resolve("isA" as const),
    onB: () => Promise.resolve("isB" as const),
  });

  const promise2 = matchType2(type, {
    onA: () => Promise.resolve("isA" as const),
    onB: () => Promise.resolve("isB" as const),
  });

  const promise3 = matchType3(type, { // 报错(TS 2769):无匹配"a" | "b"的重载
    onA: () => Promise.resolve("isA" as const),
    onB: () => Promise.resolve("isB" as const),
    });

  const [result1, result2, result3] = await Promise.all([promise1, promise2, promise3]);

  if (type === "a") {
    const data1 = result1; // 推断为"isA" | "isB"
    const data2 = result2[type]; // 推断为Promise<"isA"> | undefined
    const data3 = result3; // 正确推断为'isA'但调用matchType3时报错
  }
}

问题核心与报错说明

问题的核心在于类型收窄操作发生在调用matchType*之后,虽然将调用放在条件语句内可以正常工作,但这不符合需求。

其中matchType3的报错信息如下:

No overload matches this call.
  Overload 1 of 2, '(type: "a", fns: { onA: () => Promise<"isA">; onB: () => Promise<"isB">; }): Promise<"isA">', gave the following error.
    Argument of type '"a" | "b"' is not assignable to parameter of type '"a"'.
      Type '"b"' is not assignable to type '"a"'.
  Overload 2 of 2, '(type: "b", fns: { onA: () => Promise<"isA">; onB: () => Promise<"isB">; }): Promise<"isB">', gave the following error.
    Argument of type '"a" | "b"' is not assignable to parameter of type '"b"'.
      Type '"a"' is not assignable to type '"b"'.(2769)

临时解决办法可以为matchType2的结果添加非空断言:const data2 = result2[type]!,但希望能避免这种操作。尝试过使用条件返回类型,结果和朴素方案一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:54:52