'How to create a generic interface or type that accepts tow different interfaces that go under single array?

I want to be able to create a generic type that works with an array that accepts tow similar object but not totally equal, every thing works fine until I want to access a value that is not in both objects in this case the gender property.

// React state logic 
interface Client {
  name: string;
  clientId: string;
  weekId: string;
  gender: string;
}

interface Program {
  name: string;
  clientId: string;
  weekId: string;
  type: string;
}

export interface StateInterface {
data: (Program | Client)[];
}



//In component Issue 
const clientsArr = _globalContext.data.filter((el) => el.name === value);

// Error massage on gender Property 
/*Property 'gender' does not exist on type 'Client | Program'.
Property 'gender' does not exist on type 'Program'.*/
console.log(clientsArr[0].gender!)


Solution 1:[1]

This is correct behavior. At that point typescript has no way to know if that value is a Client or a Program. What can do is adding a property that allow you to narrow the type. Here's an example:

// Added `human` property just as an example, doesn't have to be a boolean
// You could do something like `type: "client"` and `type: "program"`, 
// it would work aswell
interface Client {
  human: true;
  name: string;
  clientId: string;
  weekId: string;
  gender: string;
}

interface Program {
  human: false;
  name: string;
  clientId: string;
  weekId: string;
  type: string;
}

Then when you access it you check for your discriminating property:

if(clientsArr[0].human){
  // At this point typescript can be sure that the property exists, so no error
  console.log(clientsArr[0].gender)
}

Solution 2:[2]

You can avoid this kind of type problem by type casting:

console.log((<Client>clientsArr[0])?.gender);

so It guarantees that clientsArr[0] type should be Client, otherwise console.log shows undefined.

Also maybe clientsArr[0] is null and the question mark before .gender prevents from Cannot read properties of undefined error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 coglialoro
Solution 2