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.
*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.