Typescript: Discriminating unions without explicitly creating the discriminant?

136 Views Asked by At

I want to pass typed data from a database into a generic transformer function. It seems like the best way to accomplish this in Typescript is via a discriminating union. But, this requires a discriminant property. Is there a way to auto-generate the discriminant? Or, is there a way to write a generic transformer function using something other than a discriminated union? I'm open to other solutions besides the kind I'm suggesting below.

type DB1 = {
  id: string
  one: string
}

type DB2 = {
  id: string
  two: string
}

type One = {
  id: number
  one: string
}

type Two = {
  id: number
  two: string
}

function transformer(x: DB1): One
function transformer(x: DB2): Two
function transformer(x: DB1 | DB2): One | Two {
  switch (x.kind) { // There is no x.kind!
    case 'DB1': return db1ToOne(x)
    case 'DB2': return db2ToTwo(x)
  }
}

The challenge is easily discriminating between DB1 and DB2. Since they come from the database library directly, I do not manually instantiate the types myself, and so I do not have an opportunity "on creation" of the objects to manually include a discriminant property. I also don't really like the idea of "hacking" into DB1 and DB2 and tacking on a discriminant just before I pass it to the transformer.

Is there a way to discriminate between these types so that the transformer works the way I want it to?

(Also, since this solution is supposed to scale to many types, don't assume there is anything else besides a potential discriminant property which can otherwise differentiate between types.)

0

There are 0 best solutions below