How can I use one of the two interfaces for the same object? For example:
interface one {
id: string
color: string
}
interface two {
id: string
numb: number
}
I have an "Item" component that receives an "item" object. This object can be of type "one" or of type "two". If I specify the type as follows, then an error appears:
const Item: React.FC<{ item: one | two }> = ({ item }) => {
///
}
Is there any solution in this case? Thank you for taking the time!
CodePudding user response:
Use extends
interface One {
id: string;
color: string;
}
interface Two {
id: string;
num: string;
}
interface Item extends One, Two {}
interface Props {
item: Partial<Item>
}
const Item: React.FC<Props> = ({ item }) => {
///
}
Here's a example
CodePudding user response:
When you use a union type, you need to narrow it via a runtime test to use non-common properties.
For instance, in your example, you can use the existence of the color
property:
const Item: React.FC<Props> = ({ item }) => {
if ('color' in item) {
// use other "one" properties
}
}
If you're going this route, for clarity I recommend skipping interfaces and using a discriminated union:
type one = {
type: 'one',
id: string,
color: string
}
type two = {
type: 'two',
id: string,
numb: number
}
const Item: React.FC<{ item: one | two }> = ({ item }) => {
if (one.type === 'one') {
// now it's much more obvious you can use 'one' properties.
}
}
If you have a type you can't change, and you have a runtime test that is obvious to you that it determines the type of interface, but it's not obvious to the compiler, another thing you can do is a type guard:
function isOne(value: one | two): type is one {
return listOfOnes.includes(value);
}
// ...
const Item: React.FC<Props> = ({item}) => {
if (isOne(item)) {
// type guard means you can use 'one' properties here...
}
}