0

How do I infer the type from a passed argument or default parameter

export type ParamList = {
  SignIn: { warningMessage?: string } | undefined
  ResetOrCreatePassword: { email: string; hasPasswordAssociated: boolean }
}

type Props = {
  text: string
  fallbackScreen?: keyof ParamList
  params?: ParamList[keyof typeof fallbackScreen] // not valid but shows the goal
}

function MenuLink({fallbackScreen = 'SignIn', params = undefined, ...rest}: Props) {
  // impl not important
}

// Cases that should work
MenuLink({ text: "Go to sign in" })

MenuLink({
  text: "Reset password",
  fallbackScreen: 'ResetOrCreatePassword', 
  params: {
    email: '[email protected]',
    hasPasswordAssociated: true
  }
}) 

// TS should warn about missing params 👇
MenuLink({
  text: "Create password",
  fallbackScreen: 'ResetOrCreatePassword'
}) 
3
  • Your first case doesn't make any sense since the only parameter in MenuLink is required. Commented Sep 15, 2022 at 15:40
  • Didn't fix the above comment's remark, so I still don't know your intent. Commented Sep 15, 2022 at 17:59
  • You are right, Good point - I had the function boiled down to the minimum to show my attention. Hope I have it right now :) Commented Sep 15, 2022 at 18:16

1 Answer 1

1

It is possible to achieve the desired behavior through the use of mapped types to generate the possible props:

type WithParams<T> = {
    [K in keyof T]: {
        text: string;
        fallbackScreen: K;
        params: T[K];
    }
}[keyof T];

type Props = {
    text: string;
    fallbackScreen?: never;
    params?: never;
} | WithParams<ParamList>;

This will give you something like this:

type Props = {
    text: string;
    fallbackScreen?: never;
    params?: never;
} | {
    text: string;
    fallbackScreen: "SignIn";
    params: { warningMessage?: string }
} | { ... }

You can see in the below playground that it also provides helpful errors.

Playground

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

Comments

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.