【问题标题】:Why typescript does not infer type that promise resolves为什么打字稿不推断承诺解决的类型
【发布时间】:2021-09-16 18:42:19
【问题描述】:
const destructPromise = <TResult>(promise: Promise<TResult>) => {
  return promise.then(data => [data, null]).catch(err => [null, err]);
};

const test = async () => Promise.resolve({ a: 1 });

const fun = async () => {
  const [a, b] = await destructPromise(test()); // Why in this example the types of variables 'a' and 'b' are inferred as any?
};

为什么在这个例子中变量 'a' 和 'b' 的类型被推断为 any?

【问题讨论】:

  • 您希望该类型解析为 TResult 吗?
  • 我希望至少类型 'a' 将被推断为 TResult |空
  • @CaptainChaos 两位船长:D

标签: typescript type-inference


【解决方案1】:

这是因为被破坏的 Promise 的返回值必须考虑到 .then.catch 两种情况的可能结果。

.then 很简单,它返回Promise&lt;(TResult | null)[]&gt;。但是 .catch 是问题所在,因为默认情况下,错误参数的类型是 any,为我们提供了该分支的返回类型 any[]

要解决此问题,请为您的函数提供一个明确的返回类型,以正确捕捉您的两种情况之间的区别:

const destructPromise = <TResult extends unknown>(promise: Promise<TResult>): Promise<[TResult, null] | [null, any]> => {
  return promise.then(data => [data, null] as [TResult, null]).catch(err => [null, err] as [null, any]);
};

现在,当您使用它时,您的变量将被赋予正确的类型!:

const test = async () => Promise.resolve({ a: 1 });

const fun = async () => {
  const [a, b] = await destructPromise(test());
  if (a) {
    const some_number = a.a
  }
};

在此示例中,a 将被赋予类型 {a: number} | null,而b 仍被键入为 any

如果您仍想删除any,则必须从.catch 块中返回一个已知类型,可能通过使用new Error(err) 包装err 参数。

【讨论】:

    【解决方案2】:

    只是@CRice 答案的扩展。

    您可以借助小函数推断所有参数。

    考虑这个例子:

    const tuple = <A, B>(a: A, b: B): [A, B] => [a, b]
    
    const destructPromise = <TResult,>(promise: Promise<TResult>) => {
        return promise
            .then(data => tuple(data, null))
            .catch((err: unknown) => tuple(null, err));
    };
    
    const test = async () => Promise.resolve({ a: 1 });
    
    const fun = async () => {
        const [a, b] = await destructPromise(test());
    };
    

    Playground

    您也可以使用as const 代替tuple

    我将unknown 用于catch(error),因为它更安全。

    您可能已经注意到,tuple 函数可以为您完成工作。所有参数都是推断出来的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-15
      • 1970-01-01
      • 2022-09-29
      • 2017-05-16
      相关资源
      最近更新 更多