Home > front end >  Typescript generics with functions Parameters
Typescript generics with functions Parameters

Time:03-07

I'm trying to open a typescript method using generics. There is an object with methods (the comment indicated different types of function parameters)

const emailTypes = {
  confirmEmail: generateConfirmEmailOptions, // { a: string, b: string;}
  restorePassword: generateRestorePasswordOptions, // { a: string, b: number;}
};

Type with keys of this object:

export type IEmailTypes = typeof emailTypes;

and the method itself:

export const getEmailOptions = <T extends keyof IEmailTypes>(emailType: T, emailData: Parameters<IEmailTypes[T]>[0]) =>
  emailTypes[emailType](emailData);

Now swears at (emailData), I can not understand why. I felt like I was doing the right thing. I pass the names of the key to T, then I take the function parameters for this key. But no, it swears if different types.

I want to make it so that when transmitting, for example confirmEmail in emailType , TS told me exactly what emailData should be

What am I doing wrong?

For clarity, I'll attach a screenshot.enter image description here

*methods in emailTypes have parameter types

CodePudding user response:

Check @jcalz answer here.

So you either sacrifice some safety by doing some casting or you'll need to refactor it a little to help TS. It may look like this:

declare const generateConfirmEmailOptions: (opts: { a: string; b: string }) => void
declare const generateRestorePasswordOptions: (opts: { a: string; b: number }) => void

interface Args {
  confirmEmail: Parameters<typeof generateConfirmEmailOptions>[0]
  restorePassword: Parameters<typeof generateRestorePasswordOptions>[0]
}

type Mapping = { [K in keyof Args]: (opts: Args[K]) => void }

const emailTypes: Mapping = {
  confirmEmail: generateConfirmEmailOptions, 
  restorePassword: generateRestorePasswordOptions, 
};

const getEmailOptions = <K extends keyof Args>(emailType: K, emailData: Args[K]) => {
  const fn = emailTypes[emailType] 
  return fn(emailData);
}

Yes, it's a bit unfortunate that you have to duplicate some code, but apparently right now is the only 100% type-safe way to do it. Let's see what future versions of TypeScript bring.

  • Related