Typescript generic function which gives component properties based on other variables

Viewed 36

This one has been puzzling me for a while, trying to create a type-safe email service.

I have an enum of possible template names:

enum TemplateName {
 EXAMPLE_TEMPLATE = "EXAMPLE TEMPLATE"
 ...
}

I have an object of default settings per template:

type EmailConfig<X = React.ComponentType> = {
 html: X
 subject: string
 ...
}

type EmailMapping: EmailConfig = {
 [key in TemplateName]: EmailConfig
}

const Emails = {
 [TemplateName.EXAMPLE_TEMPLATE]: {
    html: TestTemplate, // THIS IS A REACT FUNCTIONAL COMPONENT
    subject: "This is a test",
    ...rest
 }
 ...
}

My Templates look like so:

export interface TestTemplateProps {
  title?: string
  firstName?: string
  preview?: string
  headline?: string
  site?: string
  ...
}

export const TestTemplate: React.FC<TestTemplateProps> = ({
  title = 'Test Email',
  site = 'My Website',
  preview = 'Important Information from My Site',
  firstName = 'there',
  headline,
  children,
}) => {
  return (
  ...
  )
}

I have a generic function I want to be able to pass in an enum value and all the props of the Component that relates to that enum value.

FOR EXAMPLE

sendEmail(TemplateName.EXAMPLE_TEMPLATE, { ... })

Where { ... } is typed to TestTemplateProps interface

My current attempt at sendEmail looks like this:

async sendEmail<X extends keyof EmailMapping>(
    template: X,
    opts: React.ComponentProps<typeof Emails[X]['html']>
  ) {
...
}

I've tried just playing around (honestly I am just guessing at what to change at this point) and this is the closest I have come so far.

When I call sendEmail with above code, it forced me to pass one of the Enums, but then in the opts the only "typing" that appears is "children?" and none of the other properties in the TestTemplateProps so I think I'm close!

TIA

1 Answers

Yes. but the first thing that I wanna know is ... are you making a class for data loading and passing data in your interfaces with static function or static constructor for async data loading... if so ... I want to know the the exact problem you're facing...

Related