-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Declaration emit references imported type without importing it when inheriting static methods via CommonJS require #63353
Copy link
Copy link
Open
Description
🔎 Search Terms
declaration emit missing import typedef commonjs require static method
🕗 Version & Regression Information
- This changed between versions 5.4 and 5.5
⏯ Playground Link
N/A, as this requires multiple files
💻 Code
tsconfig.json
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"allowJs": true,
"checkJs": false,
"strict": true,
"noEmit": false,
"declaration": true,
"emitDeclarationOnly": true,
"declarationDir": "types",
"rootDir": "lib",
"skipLibCheck": true
},
"include": ["lib/**/*.js"]
}lib/Parent.js
/** @typedef {import('../Dependency')} DoubleDependency */
class Parent {}
class ParentProperty {
/**
* @returns {DoubleDependency}
*/
static myStaticMethod() {}
}
module.exports = Parent;
Parent.Property = ParentProperty;lib/Child.js
"use strict";
const Dependency = require("./Parent");
class MyChild {}
MyChild.Template = class Child extends (
Dependency.Property
) {};
module.exports = MyChild;🙁 Actual behavior
tsc emits the following types/Child.d.ts:
export = MyChild;
declare class MyChild {
}
declare namespace MyChild {
export { Child as Template };
}
declare const Child_base: {
new (): {};
myStaticMethod(): DoubleDependency; // ← uses DoubleDependency but it is never imported
};
declare class Child extends Child_base {
}
import Dependency = require("./Parent"); // ← emitted but unusedThere are two problems:
DoubleDependencyis referenced but never imported. The type flows through theChild_basesynthetic constructor type (viaParentProperty.myStaticMethod's return type), but the declaration emitter does not add an import for it.import Dependency = require("./Parent")is emitted but never referenced in the declaration file. It appears to be a leftover from theconst Dependency = require("./Parent")in the source, but since the emitted declarations use an inlined structural type forChild_baseinstead of referencingDependency.Property, the import serves no purpose.
The emitted .d.ts is not self-contained (consuming it produces):
Child.d.ts(9,23): error TS2304: Cannot find name 'DoubleDependency'.
This can be reproduced by running:
tsc --ignoreConfig --strict --noEmit --skipLibCheck false --module commonjs --target ES2017 types/Child.d.ts types/Parent.d.ts
🙂 Expected behavior
The emitted types/Child.d.ts should either:
-
Import
DoubleDependencyfrom./Parent(where it is defined as a type alias), so the reference resolves:import Dependency = require("./Parent"); // ... declare const Child_base: { new (): {}; myStaticMethod(): Dependency.DoubleDependency; };
-
Or inline the resolved type (which is
anysince'../Dependency'doesn't exist) instead of referencing a name that isn't in scope:declare const Child_base: { new (): {}; myStaticMethod(): any; };
In either case, the unused import Dependency at the bottom should be removed if it is not referenced, or moved to the top if it is.
Additional information about the issue
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels