Harshal Patil
Harshal Patil

Reputation: 21030

How to create a globally available interface/type in TypeScript?

I am creating an component library with Preact and TypeScript. I have an icon component which can be used like:

<SVGIcon name='camera' width={16} height={24} />

And, it is implemented as:

export interface SVGIconProps {
  class?: string;
  width?: string;
  height?: string;
  name: string;
};

export function SVGIcon(props: SVGIconProps) { /* return svg; */ }

In to provide better intellisense for library users, I want to narrow the type of name prop to a limited set of string literals (basically show only allowed names for icons). I can, of course, use string literals that library is providing; however, the user is also allowed to dynamically register his own additional icon sets using a register function like:

registerIcon('icon-name', jsxFunctionReturningSVGFragment);

The registerIcon function add the icon and its JSX function to an internal cache (instance of ES Map).

That question is how can I retain the narrow typing and provide auto-complete/intellisense for library users considering the fact that they can add one or more icons when consuming the library?

Is it possible to declare a dummy interface/type say MyLibIconSet at a library level which the user of the library should then override in his code-base before using the library? Something similar to how we do for declaration merging or using Global augmentation for patching missing types?

Upvotes: 1

Views: 250

Answers (1)

Kriszti&#225;n Balla
Kriszti&#225;n Balla

Reputation: 20401

I think this can be achieved with declaration merging.

You could define an interface that has a member for each possible icon. The type would be whatever you like in this case:

export interface SVGPossibleIcons {
  thumbsUp: string;
  thumbsDown: string;
  roflSmiley: string;
}

Then you could define your props like this:

export interface SVGIconProps {
  class?: string;
  width?: string;
  height?: string;
  name: keyof SVGPossibleIcons;
}

The user of the library then has to extend that interface with his/her own icons like this:

declare module "YourSVGModuleName" {
    export interface SVGPossibleIcons {
        anotherCustomSmiley: string;
    }
}

Upvotes: 2

Related Questions