I just improved dts generation in TSUP, a library to help you bundle TypeScript libraries real fast, previously you can use --dts
flag to rollup .d.ts
files, but third-party types are not resolved, for example, I often import some type utilities from the ts-essentials
library:
// index.ts
import type { MarkRequired } from 'ts-essentials'
export type Options = { foo?: string }
export type NewOptions = MarkRequired<Options, 'foo'>
export const myLib = (options: Options): NewOptions => {
return { ...options, foo: options.foo || 'default value' }
}
If you run tsup index.ts --dts
, the output dist/index.d.ts
will look like:
import { MarkRequired } from 'ts-essentials';
declare type Options = {
foo?: string;
};
declare type NewOptions = MarkRequired<Options, 'foo'>;
declare const myLib: (options: Options) => NewOptions;
export { NewOptions, Options, myLib };
The library ts-essentials
only provide types, so if you add it as one of the dependencies
in package.json
every user would have to install the whole package, even if only a single type is imported, and some people don't even use TypeScript.
Resolve external types
tsup provides a solution, which allows you to resolve and rollup external types so everything1 results in a single .d.ts
file, run tsup index.ts --dts-resolve
and the new dist/index.d.ts
would be:
/** Mark some properties as required, leaving others unchanged */
declare type MarkRequired<T, RK extends keyof T> = Exclude<T, RK> & Required<Pick<T, RK>>;
declare type Options = {
foo?: string;
};
declare type NewOptions = MarkRequired<Options, 'foo'>;
declare const myLib: (options: Options) => NewOptions;
export { NewOptions, Options, myLib };
No additional package now! 🥳
Know more about TSUP:
- GitHub: https://github.com/egoist/tsup
- Documentation: https://tsup.egoist.sh
-
--dts-resolve
will ignore packages specified in thedependencies
field inpackage.json
, meaning they're always externalized. ↩
Top comments (3)
I'm still getting imported types in the final .d.ts file. I've tried with the command line version and with the config file version. Could there be any conflicts with the tsconfig file or perhaps something else?
Aaron make sure that the import you are using is not part of dependencies or devDependencies, if you are using typescript, I would recommend using paths parameter to reference it locally then it will be included.
Eg: If you are using an internal package in a monorepo that you do not want to publish but bundle it with another package then reference it on the tsconfig.json
If A needs to be published, but B is the internal package(external module) then make sure that this is not part of A's package.json deps instead reference it on the tsconfig.json like this
"compilerOptions": {
.....
"paths": {
// Required to bundle types of common package along with index.d.ts of ovi-ui-apps
"module-b": ["../module-b/dist"]
}
......
}
where module-b dist contains the build artefacts and the types.
Thanks a ton for this man, I ended up with tsup finally after banging my head for 2 days.