4

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

0

1 Answer 1

3

Check @jcalz answer here.

So you either sacrifice type-safety by casting, or you'll need to refactor it to help the compiler. 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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the example, now I understand how it works!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.