question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Elegance of dynamic imports in TypeScript

See original GitHub issue

Bug 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

  1. 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>);
    
  2. 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

{
  "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:closed
  • Created 5 years ago
  • Reactions:25
  • Comments:32 (15 by maintainers)

github_iconTop GitHub Comments

42reactions
LunaTKcommented, Apr 21, 2019

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.

interface ButtonProps {
    onClick: () => any;
}

The interface above is just example, assuming that onClick is the only property used in Button. Then, just specify this when calling dynamic import, and error will be gone.

const Button = dynamic<ButtonProps>(import("../components/Button"));
32reactions
Mosoccommented, Dec 17, 2018

I found a workaround just now at next@7.0.2

const DynamicComponent = dynamic(
(()=>import('MyComponents')) as any,
{ /* options */ },
)

I use it for non-SSR apollo-graphql query.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation - TypeScript 2.4
Dynamic import expressions are a new feature and part of ECMAScript that allows users to asynchronously request a module at any arbitrary point...
Read more >
Dynamic import() Expressions in TypeScript - Marius Schulz
TypeScript 2.4 added support for dynamic import() expressions, which allow you to asynchronously load and execute ECMAScript modules on demand.
Read more >
Dynamic Imports with Web Components : r/typescript - Reddit
Dynamic Imports with Web Compo## Dynamic Imports with Web ... I am aware this isn't really required but curious for elegant ideas.
Read more >
Dynamic Import Expressions - TypeScript Deep Dive - Gitbook
Dynamic import expressions are a new feature and part of ECMAScript that allows users to asynchronously request a module at any arbitrary point...
Read more >
Shorter import paths in Angular - Level Up Coding
What we need to do is add a key called paths into the compilerOptions array. Here, Typescript allows us to define path aliases...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found