Home > Net >  using a generic type to accept two different types of items as a parameter
using a generic type to accept two different types of items as a parameter

Time:07-15

this should be a simple use case, but I can't seem to fine an example that covers it.

Basically I have a function that should be allowed to take two different objects, that are very similar. So, I would like to use the generic type. The function looks something like this:

const myFunction = <MyGenericType>(arrayOfObjects: MyGenericType[]) => {
  return arrayOfObjects.map((obj: MyGenericType) => ({
    id: obj.id,
    name: obj.name,
    someProperty: obj.someProperty || obj.someOtherProperty,
  }))
}

So for it's usage these would be the two types that I could pass in as a parameter:

type PotentialType1 = {
  id: string
  name: string
  someProperty: string
}


type PotentialType2 = {
  id: string
  name: string
  someOtherProperty: string
}

The issue is, if I try to do this, each of the properties accessed in myFunction get the following error:

Property X does not exist on type 'MyGenericType'.

So, id, name and someProperty all don't exist.

It seems to work flawlessly with the primitive types (such as string, number, etc), but how could I do this with the more complex ones?

Thanks!

CodePudding user response:

The problem is that your function doesn't know anything about MyGenericType. To let it know that this type will always have certain properties, you will need to add a constraint. In this case, it looks like you need your generic type to be one of two specific types, so you could tell your generic function that MyGenericType extends a union of those two types:

type PotentialType1 = {
  id: string
  name: string
  someProperty: string
}


type PotentialType2 = {
  id: string
  name: string
  someOtherProperty: string
}

const myFunction = <MyGenericType extends PotentialType1 | PotentialType2>(arrayOfObjects: MyGenericType[]) => {
  return arrayOfObjects.map((obj: MyGenericType) => ({
    id: obj.id,
    name: obj.name,
    someProperty: 'someProperty' in obj ? obj.someProperty : obj.someOtherProperty,
  }))
}

TypeScript Playground

In this example I've also had to change the setting of someProperty to use a ternary operator so TypeScript will narrow the type of obj instead of complaining that those properties don't exist on something with the type PotentialType1 | PotentialType2.

  • Related