Sam
Sam

Reputation: 1249

Typescript callback params depends on other option params

I have types like this;

type Admin = {
  propertyA: string;
  propertyB: string;
}

type User = {
  propertyC: string;
  propertyE: string;
}

interface AuthProviderProps {
  userType: 'user' | 'admin';
  onUserLoggedIn: (user) => void;
}

How can i pass right user type to onUserLoggedIn depends on userType

Upvotes: 0

Views: 59

Answers (2)

Lesiak
Lesiak

Reputation: 26066

As an alternative to generic solution by @AlexWayne, you can use a discriminated union.

I prefer it this solution over generics as you dont need to repeat type of the of the user twice (one in generic param, second in userType field)

interface AuthProviderPropsUser {
  userType: 'user';
  onUserLoggedIn: (user: User) => void;
}

interface AuthProviderPropsAdmin {
  userType: 'admin';
  onUserLoggedIn: (user: Admin) => void;
}

type AuthProviderProps = AuthProviderPropsUser | AuthProviderPropsAdmin;

const x: AuthProviderProps = {
    userType: 'user',
    onUserLoggedIn: (user) => {
      console.log(user.propertyC); // OK
      console.log(user.propertyA); // Error Property 'propertyA' does not exist on type 'User'. Did you mean 'propertyC'?
    },
}

Playground link

Upvotes: 2

Alex Wayne
Alex Wayne

Reputation: 187134

You need to use generics here to capture a type, and then reference it elsewhere.

interface AuthProviderProps<T extends 'user' | 'admin'> {
  userType: T;
  onUserLoggedIn: (user: T) => void;
}

When you would use like so:

const userProps: AuthProviderProps<'admin'> = {
  userType: 'admin',
  onUserLoggedIn(user) { // typescript knows user is of type 'admin' here
    console.log(user)
  }
}

Upvotes: 1

Related Questions