Bloated declaration files
Bug Report
The way Typescript generate d.ts files results in a lot of duplicated code which probably slow down typescript services.
In our internal project we have many files that contains the same type duplicated more than 600 times, coming from imported inlined types, resulting in ~230kb of .d.ts size increase.
🔎 Search Terms
emit declarations, dts, duplicate types, dedupe dts
🕗 Version & Regression Information
-
This is the behavior in every version I tried, and I reviewed the FAQ for entries about emit declarations, duplicate types and dedupe dts.
-
This behavior is different in v3.3.3333
⏯ Playground Link
Check the .D.TS tab in the playground
https://www.typescriptlang.org/play?ts=4.8.2#code/PTAEBkHlIaVBBAKqRAJAoqAdAES4gZVABcBDAI1AGcBTG0ASwFsAHAewCdiAKAIg5qkAxsV4BKUEwCuAG2IMWM+vKY0qAWABQIBDKptGAOxIALBlVBDStU-RqH5AkgE8W9c6AAmUxQyvEaTywtLWZ2LlAAb0sBUgD0JVUHUABfUAAzDjYmUH5BEV4AbhDNGgAPcOJLNkMqKtJQAF4YwXjE+x4Ack6xYtKKziqhGrrQSmahWLaaJK6evvLK6tqhppa4mgSZju5u3q1FweXRzzXJ1s32h135g4GI4ZXQegmpy+3rvYX7oZGq9LOby2sxu+36S0eowA5oCLsCdl87hC-qATLCNvDPrdwUdIVUGOjpiDETiHiiAFaE97E7GHMlPADWVMxczBdN+TxkzKurO+yKeOVecJ5oL5uJRxiFGJFJPZxyqBilRIRtJ+8tALG5H15SPFTwAjlqaWy1XjQBwjSqTfzRhYldSrX0gA
In a real project with long import paths between modules the size increase if more substantial. for example: https://github.com/barak007/ts-dts-dedupe/blob/master/dist/index.d.ts
💻 Code
import { create } from "./a/b/c";
export const a = create();
export const b = create();
// file: a/b/c.ts
export interface Base {}
export interface G1<T, T1> {}
export function create<T>(): G1<G1<G1<T, Base>, Base>, Base> {
return {};
}
🙁 Actual behavior
The resulting .d.ts file is:
export declare const a: import("./a/b/c").G1<
import("./a/b/c").G1<
import("./a/b/c").G1<unknown, import("./a/b/c").Base>,
import("./a/b/c").Base
>,
import("./a/b/c").Base
>;
export declare const b: import("./a/b/c").G1<
import("./a/b/c").G1<
import("./a/b/c").G1<unknown, import("./a/b/c").Base>,
import("./a/b/c").Base
>,
import("./a/b/c").Base
>;
🙂 Expected behavior
Whenever the compiler need to use an external type it can create an import * as NAME from "request"; statement, then use NAME.TYPE to access the type instead of inline it with the import() syntax.
It will turn the previous .d.ts into:
import * as ABC from "./a/b/c";
export declare const a: ABC.G1<ABC.G1<ABC.G1<unknown, ABC.Base>, ABC.Base>, ABC.Base>;
export declare const b: ABC.G1<ABC.G1<ABC.G1<unknown, ABC.Base>, ABC.Base>, ABC.Base>;
Typescript can go even further and dedupe identical types:
import * as ABC from "./a/b/c";
type Alias = ABC.G1<ABC.G1<ABC.G1<unknown, ABC.Base>, ABC.Base>, ABC.Base>;
export declare const a: Alias;
export declare const b: Alias;
The compiler will need to be hygienic here and might also generate a readable name since it might appear in user autocomplete.
This sounds like #30258.
I hope to change that "[Working as Intended]". it's a big issue for us resulting in slow builds.
See also #44044 and #49730; the former is an open issue so I'd class this a duplicate of that.
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.