Home > Software design >  How do I create a literal type for React component parameters?
How do I create a literal type for React component parameters?

Time:10-17

I created the SelectProps interface!

export interface SelectProps {
  value: string
  options: string[]
  onChange: (value: any) => void
}

I created react component!

<Select
  value="red"
  options={['dark', 'white']}
  onChange={(value) => console.log(value)}
/>

How do I make value one of the values of options ('dark' | 'white') ? That is, I want to get this type:

type Value = 'dark' | 'white'

I must say right away this solution is not suitable:

const options = ['dark', 'white'] as const
type Value = typeof options[number]

CodePudding user response:

Here is how to do it:

export interface SelectProps<O extends string> {
  value: O & {}
  options: O[]
  onChange: (value: O) => void
}

const Select = <O extends string>(props: SelectProps<O>) => <div></div>

As the others have said, SelectProps needs to be generic. We use O as an array for options and as the type for value. Important here are two things:

First, the intersection with an empty object {} for the value field. This signals to TypeScript that the value field shall not be used for inference of O.

Secondly, we constrain O to be a string. This lets TypeScript infer the string literal types 'dark' | 'white' instead of just string.

function main() {
    return (
        <div>
            <Select
                value="red" // Error: Type '"red"' is not assignable to type '"dark" | "white"'
                options={['dark', 'white']}
                onChange={(value) => console.log(value)}
            />
            <Select
                value="dark"
                options={['dark', 'white']}
                onChange={(value) => console.log(value)}
            />
        </div>
    )  
}

Playground

CodePudding user response:

You need to use typescript Generics:

export interface SelectProps<Value> {
  value: Value
  options: Value[]
  onChange: (value: Value) => void
}

But you also need to change Select component, so it also takes a type parameter, and passes it to SelectProps interface:

    function Select<Value>(props:SelectProps<Value>){
                            ...
    }

CodePudding user response:

Add your type in the interface

export interface SelectProps {
  value: Value 
  options: Value[]
  onChange: (value: Value) => void
}
  • Related