DEV Community

EGOIST
EGOIST

Posted on

Rollup dts file using TSUP

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' }
}
Enter fullscreen mode Exit fullscreen mode

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 };
Enter fullscreen mode Exit fullscreen mode

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 };
Enter fullscreen mode Exit fullscreen mode

No additional package now! 🥳


Know more about TSUP:


  1. --dts-resolve will ignore packages specified in the dependencies field in package.json, meaning they're always externalized. ↩

Top comments (3)

Collapse
 
qodesmith profile image
Aaron Cordova

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?

Collapse
 
rajeshbabu1991 profile image
Rajesh Babu

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.

Collapse
 
rajeshbabu1991 profile image
Rajesh Babu

Thanks a ton for this man, I ended up with tsup finally after banging my head for 2 days.