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.

TS 3.4: Error when passing dynamically imported generic type as a function argument

See original GitHub issue

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms: TS2322, dynamic import, dynamic import never, dynamic import generic

Code

 .\node_modules\.bin\tsc --jsx react --lib es2017 --strict index.tsx
// ===== page.tsx ======
import * as React from 'react'

export interface PageProps {
    title: string
}

export class Page extends React.Component<PageProps> {
    render() {
        return <div>{this.props.title}</div>
    }
}

// ===== index.tsx =====
import * as React from 'react'
import{ PageProps, Page } from './page'

export function myFunction<TProps>(loader: () => Promise<React.ComponentType<TProps>>) {

}

// No error
myFunction(() => Promise.resolve(Page))

// No error
const loader: () => Promise<React.ComponentType<PageProps>> = () => import('./page').then(m => m.Page)

// Error
myFunction(() => import('./page').then(m => m.Page))

Expected behavior:

No compile error. This was the behavior in TS 3.3 and earlier.

Actual behavior:

There is an error after upgrading to TS 3.4:

index.tsx:14:18 - error TS2322: Type 'Promise<typeof Page | ComponentClass<never, any> | FunctionComponen
t<never>>' is not assignable to type 'Promise<ComponentType<PageProps>>'.
  Type 'typeof Page | ComponentClass<never, any> | FunctionComponent<never>' is not assignable to type 'C
omponentType<PageProps>'.
    Type 'ComponentClass<never, any>' is not assignable to type 'ComponentType<PageProps>'.
      Type 'ComponentClass<never, any>' is not assignable to type 'ComponentClass<PageProps, any>'.
        Type 'PageProps' is not assignable to type 'never'.

14 myFunction(() => import('./page').then(m => m.Page))
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  index.tsx:4:44
    4 export function myFunction<TProps>(loader: () => Promise<React.ComponentType<TProps>>) {
                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The expected type comes from the return type of this signature.

Repro here: https://github.com/srmagura/ts-import-repro

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:10
  • Comments:16 (12 by maintainers)

github_iconTop GitHub Comments

16reactions
jantimoncommented, May 5, 2021

@sandersn those workarounds canโ€™t be used by library writers but have to be known by the consumers of the libraryโ€ฆ

it is affecting a large number of people - e.g. everyone who is using nextjs with dynamic imports: https://nextjs.org/docs/advanced-features/dynamic-import

could you please consider picking up this issue once again?

9reactions
sandersncommented, May 22, 2019

@styu

Workarounds:

  1. avoid context by extracting import('./page').then(m => m.Page):

    const loader = () => import('./app').then(m => m.Page)
    myFunction(loader)
    

    This avoids the return type inference since there is no contextual type to infer from.

  2. provide a real or fake onrejected:

    myFunction(() => import('./app').then(m => m.Page, e => null as never))
    

    This one is fake โ€” null as never disappears nicely in the type system โ€” but a real app should probably provide a fallback page in case the import fails.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is there a way I can import types using a generic parameter?
It is not possible, at least as of TypeScript 4.6, to express " import types" of a form like import(T) or typeof import(T)...
Read more >
Documentation - Conditional Types - TypeScript
But the power of conditional types comes from using them with generics. For example, let's take the following createLabel function: ts. interface IdLabel...
Read more >
The Ceylon Language
Since generic type arguments are reified at runtime, the metamodel fully captures generic types at both compile time and execution time. Attribute<String,ย ...
Read more >
More types - mypy 0.991 documentation
This section introduces a few additional kinds of types, including NoReturn , NewType , TypedDict , and types for async code. It also...
Read more >
Overview - TypeScript
During type argument inference in TypeScript 3.4, for a call to a generic function that returns a function type, TypeScript will, as appropriate,...
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