Baterka
Baterka

Reputation: 3714

Require parameter of given type based on another parameter in TypeScript

Let's have TypeScript function for sending emails:

enum ETemplate {
  EXAMPLE1, EXAMPLE2
}

function sendEmail(to: string, template: ETemplate, params: IParams): Promise<void>{
  await this.mailService.send(to, template, params);
}

interface IParams {
  // depends on template type (ETemplate)
}

How to require params depending on template type I entered? Reason why is because every template have different IParams based on ETemplate.

I know TypeScript have generics but I am not sure if I can achieve this with them...

Upvotes: 1

Views: 110

Answers (1)

elderapo
elderapo

Reputation: 374

You don't need to use generics in this case. Use discriminated unions instead:

enum TemplateType {
    Template1,
    Template2
}

type Template =
    | { type: TemplateType.Template1, params: { aaa: number } }
    | { type: TemplateType.Template2, params: { bbb: string, ccc?: boolean } };

const sendEmail = async (to: string, template: Template): Promise<void> => {
    if (template.type === TemplateType.Template1) {
        template.params.aaa; // number

        return;
    }

    if (template.type === TemplateType.Template2) {
        template.params.bbb; // string
        template.params.ccc; // boolean | undefined

        return;
    }

    template; // never
}


sendEmail("[email protected]", { type: TemplateType.Template1, params: { aaa: 123 } }); // OK
sendEmail("[email protected]", { type: TemplateType.Template2, params: { aaa: 123 } }); // Error as expected

Upvotes: 2

Related Questions