如何在与返回值相关的函数的返回上添加条件类型?

时间:2019-11-21 00:01:46

标签: typescript

我正试图围绕以下内容。我有一个功能:

export const useProject = (id: string) => {
  <project fetching logic here>

  return {
    project,
    loading: project === undefined
  }
}

基本上,如果存在项目,则loading为false,否则为project未定义。

我的问题是使用以下代码:

const { project, loading } = useProject(id)

if (loading) return 'loading…'

return project.title

typescript抱怨project在最终返回时可能是不确定的。在projectloading的情况下,如何更新函数以使打字稿知道false存在?

1 个答案:

答案 0 :(得分:2)

这里的主要问题是,即使您将useProject()的返回值表示为discriminated union,其中loading属性也可以用来确定project属性定义后,一旦将子属性复制到单独的projectloading变量中,TypeScript编译器将无法遵循它们之间的相关性。

也就是说,您可以像这样优化useProject()的类型:

export const useProject = (id: string) => {
    const project = Math.random() < 0.5 ? ({ title: "hey" } as Project) : undefined;
    return {
        project,
        loading: project === undefined
    } as { project: Project, loading: false } | { project: undefined, loading: true };
}

,但以下代码仍会给您一个错误:

const { project, loading } = useProject("zoop")
if (loading) return 'loading…'
return project.title; // error! Object is possibly undefined

如果您想让编译器了解检查loadingproject类型的影响,则需要将它们称为公共父区分联合对象的属性:

const projStatus = useProject("zoop");
if (projStatus.loading) return 'loading…';
return projStatus.project.title; // okay

在GitHub中有一些未解决的问题,建议编译器应基于属性或其他类型保护检查(已复制到其他变量,例如microsoft/TypeScript#12184和{ {3}},但响应基本上是“ microsoft/TypeScript#24865”:

  

这将要求我们跟踪一个变量的特定值对其他变量的影响,这将给控制流分析仪增加很多复杂性(以及相关的性能损失)。尽管如此,我们仍将其作为建议。

因此,我不会等待解决此问题。如果您可以将代码重构为不破坏结构的有区别的联合,那就太好了。否则,您将需要使用that's probably too hard或等效命令来使编译器的警告静音:

return project!.title; // okay, using non-null assertion

好的,希望能有所帮助;祝你好运!

type assertions