Search code examples
typescripttypesinterfacereact-functional-component

Typescript allow only one property


This code allow me to send in props just one of the options but not the other, for example:

<Drawer volunteer />

now it's 3 properties, but if there is more how can i write it more generic ?

The Drawer types declaration:

type DrawerTypes =
    { volunteer: boolean } & { rescues?: never } & { map?: never } |
    { volunteer?: never } & { rescues: boolean } & { map?: never } |
    { volunteer?: never } & { rescues?: never } & { map: boolean };

Solution

  • You can use a mapped type to map over the keys, picking the specific key and making the others never:

    type OneOf<T> = {
        [K in keyof T]: Pick<T, K> & Partial<Record<Exclude<keyof T, K>, never>>;
    }[keyof T]
    

    The new definition of DrawerTypes would be

    type DrawerTypes = OneOf<{ volunteer: boolean; rescues: boolean; map: boolean }>;
    

    Admittedly, the tooltip of DrawerTypes is not particularly helpful, so if you add this extra bit,

    type OneOf<T> = {
        [K in keyof T]: Pick<T, K> & Partial<Record<Exclude<keyof T, K>, never>>;
    }[keyof T] extends infer O ? { [K in keyof O]: O[K] } : never;
    

    you can see that DrawerTypes is equivalent to

    type DrawerTypes = {
        volunteer: boolean;
        rescues?: undefined;
        map?: undefined;
    } | {
        rescues: boolean;
        volunteer?: undefined;
        map?: undefined;
    } | {
        map: boolean;
        volunteer?: undefined;
        rescues?: undefined;
    }
    

    which is the same as your original definition of DrawerTypes.

    Playground


    note: key?: undefined is equivalent to key?: never without exactOptionalPropertyTypes.