Typescript 惰性导入传递的类型是什么

问题描述 投票:0回答:2

我是 typescript 的新手,我不知道如何解决这个问题。我在多个文件中有一些惰性导入,我想用

React.Suspense
包装它们,所以我认为最好的解决方案是这个:

带有惰性导入的通用 .ts 文件

import Loadable from './Loadable'
import { lazy } from 'react'

const WrappedComponent = Loadable(lazy(() => import('path/to/my/component')));

...
// using wrapped component, for example:
// return <WrappedCompnent />
...

Loadable.tsx

import React, { Suspense } from 'react';
import Loader from './Loader';

const Loadable = (child: JSX.Element) => (props: object) => {
    const Component = child;
    return (
        <Suspense fallback={<Loader />}>
            <Component {...props} />
        </Suspense>
    );
}

export default Loadable;

我试图用很多东西代替

JSX.Element
,但我不断收到这些错误:

Argument of type 'LazyExoticComponent<() => Element>' is not assignable to parameter of type 'Element'.
const WrappedComponent = Loadable(lazy(() => import('path/to/my/component')));

JSX element type 'Component' does not have any construct or call signatures.
<Component {...props} />

我必须用什么来代替

JSX.Element
才能让它发挥作用?
提前致谢

typescript lazy-loading
2个回答
1
投票

您可以从

loadable
库围绕
@loadable/component
创建一个精简的抽象,因此
Loader
组件只导入一次。

打字来自图书馆本身。

import loadable, {
  DefaultComponent,
  LoadableComponent,
} from "@loadable/component";
import React from "react";

const Loader = () => <div>Loading...</div>;

const Loadable = <TProps,>(
  loadFn: (props: TProps) => Promise<DefaultComponent<TProps>>
): LoadableComponent<TProps> =>
  loadable(loadFn, { fallback: <Loader /> });

export default Loadable;

然后在另一个文件中:

import Loadable from "./Loadable";

const OtherComponent = Loadable(() => import("path/to/component"));

const ParentComponent = () => {
  return (
    <div>
      <OtherComponent /* props for OtherComponent */ />
    </div>
  );
}

0
投票
const Loadable = (child: JSX.Element) => (props: object) => {

JSX.Element
不是
child
参数的正确类型。 React 组件是一个函数(或类),它接受一个 props 对象并 returns a
JSX.Element
(或
null
)。所以
JSX.Element
描述的是组件的返回类型而不是组件本身。

React 组件的类型是

ComponentType<P>
其中
P
是道具的类型。

我们正在处理

React.lazy
导入,所以我们需要另一个是类型上的另一层包装。您的
child
参数不是组件,而是组件的
lazy
导入。

lazy
组件的类型是
LazyExoticComponent<T extends ComponentType<any>>
其中
T
是组件的类型。如果你有道具
P
你会使用
LazyExoticComponent<ComponentType<P>>
.

你真的不知道组件 props 的类型

P
,因为它对于你包装的每个组件都是不同的。您当前使用的是模糊类型
object
,但这不会为您提供良好的类型支持。

我们可以使用泛型

P
来描述inner/
child
组件的props。这样
WrappedComponent
将根据它包装的组件类型具有正确的道具类型。

这将我们带到:

const Loadable = <P extends any>(
    child: React.LazyExoticComponent<React.ComponentType<P>>
) => (props: P) => {

这非常接近,但它会给你一个关于 refs 的错误:

Type 'unknown' is not assignable to type 'PropsWithRef<P & { children?: ReactNode; }>'.

您的高阶组件不转发引用,因此我们需要在类型中指定返回的

WrappedComponent
不接受
ref
道具。我们可以使用另一个内置的 React 类型来做到这一点
PropsWithoutRef
.

const Loadable = <P extends any>(
    child: React.LazyExoticComponent<React.ComponentType<P>>
) => (props: React.PropsWithoutRef<P>) => {

您可以导入类型而不是使用

React.TypeName
。看起来像:

import { lazy, Suspense, LazyExoticComponent, PropsWithoutRef, ComponentType } from 'react';

const Loadable = <P extends any>(
    child: LazyExoticComponent<ComponentType<P>>
) => (props: PropsWithoutRef<P>) => {
© www.soinside.com 2019 - 2024. All rights reserved.