Home > OS >  TypeScript interfaces React
TypeScript interfaces React

Time:12-14

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...
  }
}
  • Related