Typescript: Cannot import properties from module.exports as types in JSDoc

Created on 18 Jan 2019  Β·  3Comments  Β·  Source: microsoft/TypeScript


TypeScript Version: 3.3.0-dev.20190118


Search Terms: jsdoc import module.exports has no exported member

Code

a.js

class A {}

module.exports = {A}

b.js

// @ts-check
class B {
    // In the JSDoc below, VSCode intellisense does not recognize parameter a as type A.
    // Instead it shows the error:
    //   Namespace '".../a".export=' has no exported member 'A'

    /**
     * @param {import('./a').A} a
     */
    constructor (a) {
        this.a = a
    }
}

Expected behavior
Parameter a of the constructor should be recognized as type A, which is accessible via the A property of module.exports from a.js.

Actual behavior
Intellisense reports the error: Namespace '".../a".export=' has no exported member 'A'.

Notes
@param {import('./a')} a does not give an error, but it resolves to type {A: typeof A} instead of A.

If a.js is modified with module.exports = A, then import('./a') resolves to A, however this restricts a.js to only exporting one type.

Bug JavaScript

Most helpful comment

I also had problems with this. A workaround which I have (unfortunately) used is:

InstanceType<import('./a')['A']>

import('./a')['A'] has type typeof A (i.e. the type of the class), so InstanceType<> needs to be used to get the instance

However I would much prefer it to work as import('./a').A

All 3 comments

This bug is currently blocking our team from adopting ts-check into our Javascript codebase, as we have .js files that export classes, and those classes can't be used in our ts-checked files until this bug is resolved.

As a workaround, we could define our own .d.ts files for the modules in question, but this is a lot of what we feel is duplicate work - the types are already defined in jsdoc format inline in the files.

I also had problems with this. A workaround which I have (unfortunately) used is:

InstanceType<import('./a')['A']>

import('./a')['A'] has type typeof A (i.e. the type of the class), so InstanceType<> needs to be used to get the instance

However I would much prefer it to work as import('./a').A

I have found that using exports.Thing = Thing is recognized properly, while using

module.exports = { Thing };

is not.

Was this page helpful?
0 / 5 - 0 ratings