skip to Main Content

I am kinda a newbie with TypeScript, and I am using it on a real project along with React.

I saw a post where the writter indicates two ways of declare conditional props in React using Typescript.

The writer indicates two ways to declare conditional props in React using TypeScript.

I tried the solution using generics (because I want to approach it that way), and I did not get TypeScript warning me about the type that should be the prop called "level" after checking if the authenticated prop was true.

Here’s the code:

type Props<T extends boolean> = {   
  authenticated: T;   
  level: T extends true ? 'basic' | 'admin' : 'guest'
}; 

const User = <T extends boolean>(props: Props<T>) => { 
  if (props.authenticated) { 
    return <>Profile ({props.level})</>; } 
  return <>{props.level}</> 
};

2

Answers


  1. Why would you expect a warning? Your usage of level in both cases is valid, it’s a string unless if I am missing your point

    Login or Signup to reply.
  2. This is what you have now:

    type Props<T extends boolean> = {   
      authenticated: T;   
      level: T extends true ? 'basic' | 'admin' : 'guest'
    }; 
    
    const User = <T extends boolean>(props: Props<T>) => { 
      return props.level 
    }
    
    const guestUser = User({ authenticated: false, level: 'guest' }); // guest
    const basicUser = User({ authenticated: true, level: 'basic' });  // basic
    const adminUser = User({ authenticated: true, level: 'admin' });  // admin
    
    console.log(guestUser);
    console.log(basicUser);
    console.log(adminUser);
    

    You should define two different user types and then create a discriminated union:

    type AuthenticatedUser = {
      authenticated: true;
      level: 'basic' | 'admin';
    };
    
    type GuestUser = {
      authenticated: false;
    };
    
    type UserProps = AuthenticatedUser | GuestUser;
    
    const User = <T extends UserProps>(props: T) => {
      return 'level' in props ? props.level : 'guest';
    }
    
    const guestUser = User({ authenticated: false }); // guest
    const basicUser = User({ authenticated: true, level: 'basic' });  // basic
    const adminUser = User({ authenticated: true, level: 'admin' });  // admin
    

    Here is how you can apply the types above to your component:

    type AuthenticatedUser = {
      authenticated: true;
      level: 'basic' | 'admin';
    };
    
    type GuestUser = {
      authenticated: false;
    };
    
    type UserProps = AuthenticatedUser | GuestUser;
    
    const User = <T extends UserProps>(props: T) => {
      if (!props.authenticated) {
        return <>Guest</> 
      }
      return <>Profile ({props.level})</>; } 
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search