缩小打字稿中的联合类型

时间:2018-08-31 09:58:09

标签: typescript

我有以下代码:

export async function loadInitialProps(routes: AsyncRouteProps[], pathname: string, ctx: any): Promise<InitialProps> {
  const promises: Promise<any>[] = [];

  const match = routes.find((route: AsyncRouteProps) => {
    const matched = matchPath(pathname, route);

    if (matched && route.component && isAsyncComponent(route.component)) {
      promises.push(
        route.component.load
          ? route.component.load().then(() => route.component.getInitialProps({ matched, ...ctx }))
          : route.component.getInitialProps({ matched, ...ctx })
      );
    }

    return !!matched;
  });

  return {
    match,
    data: (await Promise.all(promises))[0]
  };
}

我认为我可以使用受保护的isAsyncComponent函数来缩小联合类型:

export function isAsyncComponent(Component: AsyncRouteableComponent): Component is AsyncRouteComponentType<any> {
  return (<AsyncRouteComponentType<any>>Component).load !== undefined;
}

我的AsyncRouteableComponent类型是联合类型:

export type AsyncRouteableComponent<Props = any> =
  | AsyncRouteComponentType<RouteComponentProps<Props>>
  | React.ComponentType<RouteComponentProps<Props>>
  | React.ComponentType<Props>;

但是打字稿认为解析的承诺函数route.component.load().then(() => route.component.getInitialProps({ matched, ...ctx }))中的代码不是我期望的类型。

if (matched && route.component && isAsyncComponent(route.component)) {
  promises.push(
    route.component.load
      ? route.component.load().then(() => route.component.getInitialProps({ matched, ...ctx }))
      : route.component.getInitialProps({ matched, ...ctx })
  );
}

我收到错误消息:

Property 'getInitialProps' does not exist on type
'AsyncRouteableComponent<any>'.   Property 'getInitialProps' does not
exist on type 'ComponentClass<RouteComponentProps<any,
StaticContext>>'.

因此,在我的警卫条款之后,它似乎没有缩小范围。

我可以通过执行此操作来修复它,但是我认为Guard函数将意味着我不需要这样做:

if (matched && route.component && isAsyncComponent(route.component)) {
  const component = route.component as AsyncRouteComponentType<any>;

  promises.push(
    component.load
      ? component.load().then(() => component.getInitialProps({ matched, ...ctx }))
      : component.getInitialProps({ matched, ...ctx })
  );
}

1 个答案:

答案 0 :(得分:1)

缩小诸如route之类的可变局部变量并不适用于诸如then回调之类的回调内部,因为TypeScript不相信在执行回调之前不会重新分配该局部变量。有关更多信息,请参见this thread。解决方法是在调用保护功能之前将route(或route.component)复制到const变量中。