【问题标题】:Why doesn't Typescript infer return values correctly when possible return object types are specifically defined?当可能的返回对象类型被明确定义时,为什么 Typescript 不能正确推断返回值?
【发布时间】:2021-08-04 06:13:45
【问题描述】:

我试图了解 Typescript 如何从函数调用中推断返回值。假设我有一个名为sendRequest 的函数,它可以返回两个特定格式的对象。为什么 Typescript 不能知道如果 loadingtrue,那么 data 的唯一可能值是 null,如果 loadingfalse,那么 @987654328 唯一可能的值@ 是 Data 类型?它仍然说data 可能是null,即使根据列出的可能返回类型这是不可能的。

type Data = { firstName: string; lastName: string };

type ReturnType =
  | { loading: true; data: null }
  | { loading: false; data: Data };

const sendRequest = (fetch: boolean): ReturnType => {
  if (fetch) {
    return { loading: true, data: null };
  }

  return { loading: false, data: { firstName: 'Bart', lastName: 'Simpson' } };
};

const { loading, data } = sendRequest(true);

if (loading) {
  data; // <-- Typescript says that `data` can be either `Data` or `null`, while based on the return type, and since `loading` if `true`, `data` can't be `null`.
}

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    在您解构变量之前,这将作为discriminated union 工作。 TypeScript 可以理解 union 的数据类型取决于 loading 的值,但是一旦将其拆分为两个变量,它就不会保留此信息。

    const ret = sendRequest(true);
    
    if (!ret.loading) {
      ret.data; // <-- This is now of type Data, not null.
    }
    

    Playground Link

    正如jcalz 在 cmets 中指出的那样,您请求的行为被跟踪为microsoft/TypeScript#30581。 (感谢 jcalz!)

    【讨论】:

    【解决方案2】:

    首先值得注意的是,您不想使用 ReturnType 作为自定义类型名称,因为它实际上在 TypeScript 2.8 中具有保留用途。

    但要回答您的问题:TypeScript 抱怨的原因是因为您就是这样指定返回类型的。当loadingtrue 时,datanull

    type Response =
      | { loading: true; data: null }
      | { loading: false; data: Data };
    

    事实上,我很惊讶 TypeScript 甚至将其键入为 Data | null 而不是单独的 null。 TS Playground 中确实如此:

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2018-06-04
      • 2023-03-18
      • 2020-05-07
      • 2019-08-21
      • 2014-02-11
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多