wonderful-panda/vue-tsx-support

Is it possible to lazy load components and use them in TSX?

Opened this issue · 5 comments

const LazyComp = () => import('@/LazyComp');

and somewhere below in render function:

<LazyComp />

Runtime is ok, but Typescript is not:

JSX element type 'Promise<typeof import("path/to/LazyComp")>' is not a constructor function for JSX elements.
  Type 'Promise<typeof import("path/to/LazyComp")>' is missing the following properties from type 'Element': isRootInsert, isComment

Currently, async components are not supported.

As a workaround, you can let async components pretend normal component like below.

export function pretendNormalComponent<A extends Promise<typeof Vue>>(
  factory: () => A
): A extends Promise<infer V> ? V : never {
  return factory as any;
}

const LazyComp = pretendNormalComponent(() => import("@/LazyComp"));

Leave this issue opened until async component will be supported formally.

I tried this but got an issue.

Severity	Code	Description	Project	File	Line	Suppression State
Error	TS2322	(TS) Type 'Promise<typeof import("C:/dev/IO-Board.Management.Portal/apps/IO-Board.Management.Portal/src/components/OLMap")>' is not assignable to type 'Promise<VueConstructor<Vue>>'.
  Type 'typeof import("C:/dev/IO-Board.Management.Portal/apps/IO-Board.Management.Portal/src/components/OLMap")' is missing the following properties from type 'VueConstructor<Vue>': extend, nextTick, set, delete, and 9 more.	C:\dev\IO-Board.Management.Portal\apps\IO-Board.Management.Portal (tsconfig or jsconfig project)	C:\dev\IO-Board.Management.Portal\apps\IO-Board.Management.Portal\src\pages\index.tsx	14	Active

The component look like:

@Component
export default class OLMap extends tsx.Component<OLMapOptions>{
...
}

Marked in Bold is what helped me to achieve the same.

import("./lib/select-list").then((m) => m.default)

More details follows:

export function pretendNormalComponent<A extends Promise<typeof Vue>>(
  factory: () => A
): A extends Promise<infer V> ? V : never {
  return factory as any;
}

const EmployeeList = pretendNormalComponent(
  () => import("./lib/select-list").then((m) => m.default)
);
export { EmployeeList };

My Component look like

import Vue from "vue";
import { VNode } from "vue";
import Component from "vue-class-component";
import * as tsx from "vue-tsx-support";

@Component
export default class EmployeeList extends Vue{
  _tsx!: tsx.DeclareProps<
    tsx.PickProps<
      EmployeeList,
      | "store"
      | "label"
      | "rules"
    >
  >;
}