javascript - Standardvärde från Union-typ efter defaultProps-värde i React Typescript
Jag vill göra en Dropdown-komponent med två versioner, en som kan returnera flera valda värden och en som returnerar ett enda valt värde. Allt detta bestäms av en enda prop som kallas variant. Denna variant har unionstyp single | multiple. Så här ser det ut:
type MyOption = { label: any; value: any };
type MyDropdownProps =
| {
variant?: "single";
options: [];
onChange: (values: MyOption) => void;
}
| {
variant?: "multi";
options: [];
onChange: (values: MyOption[]) => void;
};
const MyDropdown = (props: MyDropdownProps) => {
return <pre>{JSON.stringify(props)}</pre>;
};
const Render = () => {
return <MyDropdown options={[]} variant="single" onChange={(evt) => {}} />;
};
du ser att detta fungerar korrekt om vi specificerar variant-egenskapen:
Min fråga är vad händer om vi inte vill specificera variant-egenskapen? Vad händer om vi redan specificerar den från defaultProps?
const MyDropdown = (props: MyDropdownProps) => {
return <pre>{JSON.stringify(props)}</pre>;
};
MyDropdown.defaultProps = {
variant: "single"
};
Du ser, onChange returnerar inte rätt data, det returnerar med any-typ. Hur fixar vi detta? Jag har spenderat veckor på att försöka hitta svaret men har fortfarande inte hittat det än :(
Svar #1
Definiera dina props och komponent som generiska och använd varianttypen för att bestämma parametertypen för onChange.
Eftersom din variant bara kan vara en av två typer, skulle jag välja en enklare Boole-typ som bestäms av närvaron av en multiple-egenskap (precis som <select>).
interface MyDropDownProps<Multiple extends Boolean> {
multiple?: Multiple;
options: MyOption[];
onChange: (values: Multiple extends true ? MyOption[] : MyOption) => void;
}
Du kan sedan definiera din generiska komponent
const MyDropdown = <Multiple extends Boolean>(
props: MyDropDownProps<Multiple>
) => {
return <pre>{JSON.stringify(props)}</pre>;
};
Svar #2
Tänk på det här exemplet:
import React from 'react'
type MyOption = { label: any; value: any };
type MyDropdownProps =
{
options: [];
onChange: (values: MyOption[] | MyOption) => void;
};
const MyDropdown = (props: MyDropdownProps) => {
return <pre>{JSON.stringify(props)}</pre>;
};
const Render = () => {
return <MyDropdown options={[]} onChange={(evt /* MyOption[] | MyOption */) => { }} />;
};
Lekplats
Om du inte vill specificera variant-egenskapen, då behöver du egentligen inte en sammanslagning av egenskaper. Du behöver en sammanslagning av onChange-argument.




