Elegance of dynamic imports in TypeScript
See original GitHub issueBug report
Describe the bug
This is a follow-up to https://github.com/zeit/next.js/issues/3389, which I cannot comment since the discussion is closed by the bot. The issue is to do with how dynamic imports work in TypeScript and it is still observed in Next 6.0.
To Reproduce
The example is copy-pasted from a comment by @mohammedzamakhan:
import dynamic from "next/dynamic";
const Button = dynamic(import("../components/Button"));
The above code produces the following error:
Argument of type 'Promise<typeof "/components/Button" >' is not assignable to parameter of type 'Promise<ComponentType<{}>>'.
Expected behavior
I expected Button
to be a React component, just as when I use a non-dynamic import:
import Button from "../components/Button";
Workarounds
-
Inspired by https://stackoverflow.com/a/49272129/1818285
import unusedModule from "../components/Button"; type ButtonType = typeof unusedModule; const Button = dynamic((import("../components/Button") as any) as Promise<ButtonType>);
-
Obtained through trial and error
const Button = dynamic(import("../components/Button").then(module => module.default));
Both solutions are unintuitive, so I’m wondering if there is a more elegant way of correctly deriving component types during dynamic imports. Can it be the case that @zeit/next-typescript is suggesting a sub-optimal tsconfig (which I followed)? How to just make this notation work?
const Button = dynamic(import("../components/Button"));
System information
- OS: macOS
- Version of Next.js: e.g. 6.0.3
- @zeit/next-typescript: 1.0.1
- tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"jsx": "preserve",
"allowJs": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": true,
"skipLibCheck": true,
"strictNullChecks": true,
"baseUrl": ".",
"lib": ["dom", "es2016"]
},
"include": ["src/**/*"]
}
Issue Analytics
- State:
- Created 5 years ago
- Reactions:25
- Comments:32 (15 by maintainers)
Top GitHub Comments
I also had same problem and solved it in a way of which makes use of generics.
First, you should define pops of your target component, Button in this case, if not exists.
The interface above is just example, assuming that
onClick
is the only property used inButton
. Then, just specify this when calling dynamic import, and error will be gone.I found a workaround just now at next@7.0.2
I use it for non-SSR apollo-graphql query.