[Original post edited to simplified example]
I want to create a component that will take one pair of values (both values based on the same type
-> value
, setValue
), and, based on it, will run functions depending on those types. To fully illustrate the situation:
AnimalAndCatTypes.ts:
export interface Animal {
type: string,
age: number
}
export interface Cat extends Animal {
typeOfCat: string,
}
ChangeSpecies.tsx:
import React from "react";
import { Animal, Cat } from "./AnimalAndCatTypes";
interface AnimalVersion {
value: Animal;
setValue: React.Dispatch<React.SetStateAction<Animal>>;
}
interface CatVersion {
value: Cat;
setValue: React.Dispatch<React.SetStateAction<Cat>>;
}
type Props = AnimalVersion | CatVersion;
const ChangeSpecies = (props: Props): JSX.Element => {
const { value, setValue } = props;
const handleChange = (data: string) => {
setValue({ ...value, type: data });
};
return (
<form>
<label>
<input
type="text"
value={value.type}
onChange={(data) => handleChange(data.target.value)}
/>
</label>
</form>
);
};
export default ChangeSpecies;
ExampleComponent.tsx:
import React, { useState } from "react";
import { Animal, Cat } from "./AnimalAndCatTypes";
import ChangeSpecies from "./ChangeSpecies";
const ExampleComponent = (): JSX.Element => {
const [animal, setAnimal] = useState<Animal>({
type: "dog",
age: 2
});
const [cat, setCat] = useState<Cat>({
type: "cat",
age: 1,
typeOfCat: "persian"
});
return (
<div>
<ChangeSpecies value={animal} setValue={setAnimal} />
<ChangeSpecies value={cat} setValue={setCat} />
</div>
);
};
export default ExampleComponent;
The problem is in setValue
where the typescript says that there can't be Animal
used in React.Dispatch<React.SetStateAction<Cat>>
because of missing typeOfCat
.
How to create a type in which ts will know that Props
are either Cat
or Animal
when creating component by checking that value
and setValue
are from one pair. Later, depending on that pair of types, will take the proper setValue
type which is linked to value
type and cannot mix with another?
[Added in edit]
Link to reproduction: https://codesandbox.io/s/zealous-mirzakhani-1x4kz?file=/src/App.js