Skip to content

Errors in generated declaration files #37552

@ernestostifano

Description

@ernestostifano

TypeScript Version: 3.9.0-dev.20200324

Search Terms: declaration errors, declaration files, TS1147, TS2307, TS2503

(ISSUE EXPLANATION BELOW)

Code

Source:

./file-a.js

/**
 * @namespace myTypes
 * @global
 * @type {Object<string,*>}
 */
const myTypes = {
    // SOME PROPS HERE
};

/** @typedef {string|RegExp|Array<string|RegExp>} myTypes.typeA */

/**
 * @typedef myTypes.typeB
 * @property {myTypes.typeA}    prop1 - Prop 1.
 * @property {string}           prop2 - Prop 2.
 */

/** @typedef {myTypes.typeB|Function} myTypes.typeC */

export {myTypes};

./file-b.js

import {myTypes} from './file-a.js';

/**
 * @namespace testFnTypes
 * @global
 * @type {Object<string,*>}
 */
const testFnTypes = {
    // SOME PROPS HERE
};

/** @typedef {boolean|myTypes.typeC} testFnTypes.input */

/**
 * @function testFn
 * @description A test function.
 * @param {testFnTypes.input} input - Input.
 * @returns {number|null} Result.
 */
function testFn(input) {
    if (typeof input === 'number') {
        return 2 * input;
    } else {
        return null;
    }
}

export {testFn, testFnTypes};

Generated Declarations:

./file-a.d.ts

/**
 * @namespace myTypes
 * @global
 * @type {Object<string,*>}
 */
export const myTypes: {
    [x: string]: any;
};
export namespace myTypes {
    export type typeA = string | RegExp | (string | RegExp)[];
    export type typeB = {
        /**
         * - Prop 1.
         */
        prop1: string | RegExp | (string | RegExp)[];
        /**
         * - Prop 2.
         */
        prop2: string;
    };
    export type typeC = Function | typeB;
}

./file-b.d.ts

/** @typedef {boolean|myTypes.typeC} testFnTypes.input */
/**
 * @function testFn
 * @description A test function.
 * @param {testFnTypes.input} input - Input.
 * @returns {number|null} Result.
 */
export function testFn(input: boolean | Function | myTypes.typeB): number; // TS2503 ERROR HERE!
/**
 * @namespace testFnTypes
 * @global
 * @type {Object<string,*>}
 */
export const testFnTypes: {
    [x: string]: any;
};
export namespace testFnTypes {
    export type input = boolean | Function | myTypes.typeB;
    import { myTypes } from "./file-a.js"; // TS1147, TS2307 ERRORS HERE!
}
// WHY IS ABOVE IMPORT STATEMENT NOT PLACED HERE? MANUALLY DOING IT, APPARENTLY SOLVES THE ISSUE.

Issue explanation:

TypeSctript does a very good job generating declaration files based on existing JS files, even in complex scenarios.

However, some errors appear when TypeScript decides to import declarations from other files. This happens when referenced declarations are sufficiently large (as in this example) to not be just copied.

In the ./file-b.d.ts generated declaration file I get the following errors in order of appearance (see code):

  • TS2503: Cannot find namespace 'myTypes'.
  • TS1147: Import declarations in a namespace cannot reference a module.
  • TS2307: Cannot find module './file-a.js' or its corresponding type declarations.

When the import statement is moved outside of the namespace, all errors disappear (makes sense from a JS point of view).

Beside this highlighted errors, only seen when opening the generated declaration files. Everything seems to work as intended (Type checking, auto-completion, etc.). Even when consuming the compiled library with the generated declaration files included (with those "errors" present).

Expected behavior:

No error to be present in generated declaration files.

Actual behavior:

Errors are present as explained above.

Playground Link: Not possible because import/export involved.

Related Issues: None.

Additional Details:

TypeScript Configuration
{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "Node",
        "lib": ["ESNext", "DOM"],
        "allowJs": true,
        "checkJs": true,
        "strict": true,
        "noImplicitAny": false,
        "strictNullChecks": false,
        "types": ["node", "mocha", "chai"],
        "esModuleInterop": false,
        "forceConsistentCasingInFileNames": true,
        "useDefineForClassFields": true
        "noEmit": false,
        "noEmitOnError": false,
        "declaration": true,
        "emitDeclarationOnly": true,
        "declarationDir": "./types"
    },
    "files": ["./src/index.js"],
    "exclude": ["./src/__tests__/**/*.js"]
}

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions