Search code examples
typescriptnpmpublish

How do I handle types from optional peer dependencies when publishing a TypeScript package?


When publishing a TypeScript package to npm that provides a function that accepts input from either one peer dependency or another, how do I define the optional peer dependencies?

import { ExternalFoo } from 'foo';
import { ExternalBar } from 'bar';

export const customPackage = (source: ExternalFoo | ExternalBar) => {
    /* ... */
}

How do I prevent people using my package from getting errors when one of the two options is missing?


Solution

  • Your situation is a case that currently TypeScript does not support well.

    Let's first summarize your situation:

    1. foo and bar is your optional dependency, meaning you expect your consumer will use one of them along with your library.
    2. You are only using the type information from those libraries, meaning you don't have any code dependency and don't want to add them as dependencies in your package.json
    3. your customPackage function is public.

    Because of point 3, you need to include the type in your library typings, meaning you need to add foo and bar as dependencies. This contradicts with point 1 and 2.

    If the typings of foo and bar comes from DefinitelyTyped (i.e. from package @types/foo and @types/bar), then you can add them as your dependencies in package.json. That will solve the problem.

    If the typings of foo and bar are distributed with the libraries themselves, you have to either include the libraries as dependencies (which you don't want), or create a replicate of the types ExternalFoo and ExternalBar yourself.

    This means you will cut yourself off from depending on foo and bar.

    Another way is looking at your library closely and sees if there is any harm in including the foo and bar as dependencies. Depending on the nature of your library, it might be not as bad as you think.

    Personally, I typically will go for declaring the types myself. JavaScript is a dynamic langauge to begin with.