Repository navigation
Errors in generated declaration files #37552
Description
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"]
}
Activity
ernestostifano commentedon Mar 24, 2020
Ryan Cavanaugh (@RyanCavanaugh) Wesley Wigham (@weswigham) I've run additional tests and it seems that this issue is causing problems when consuming the generated declaration files. Specifically, typescript won't compile a project if a package with the above faulty declarations is being used.
I would suggest to rise priority for this bug. TypeScript 4 might be too far in the future.
ernestostifano commentedon Mar 24, 2020
In some scenarios, when there is a name conflict, moving the import statement out of the namespace might not be enough. Maybe import with alias should be used in this cases.
It is strange, because I remember seeing the import with alias strategy in some generated declaration files in the past. It seems that the generation logic is not consistent.
Example:
ernestostifano commentedon Mar 25, 2020
Ryan Cavanaugh (@RyanCavanaugh) Wesley Wigham (@weswigham) sorry to bother you again. If you point me to the section in your codebase where this logic is defined, I would be glad to fix it myself. Please let me know.
weswigham commentedon Mar 25, 2020
In
checker.ts, the body ofserializeSymbolAsFunctionNamespaceMergeor thereabouts.