ts-morph icon indicating copy to clipboard operation
ts-morph copied to clipboard

Method to discover what the discriminant properties of a union type are

Open jasonkuhrt opened this issue 3 years ago • 5 comments

Is your feature request related to a problem? Please describe.

One of the features of Tydoc is to extract union types and discover if it is a discriminant union or not. If it is, which property or properties can be used as discriminators.

I think this feature would be useful to others generally so thought it perhaps should be a method on the union type class.

jasonkuhrt avatar Nov 13 '20 01:11 jasonkuhrt

My simple probably not optimal logic this currently is:

export function getDiscriminantPropertiesOfUnionMembers(
  members: tsm.Type[]
): (tsm.PropertySignature | tsm.MethodSignature)[] {
  const membersProperties = members.map((m) => getProperties(m))
  const commonMemberProperties = intersectionBy(...membersProperties, (p) => {
    return p.getName()
  })
  return commonMemberProperties
}

export function getProperties(t: tsm.Type): (tsm.PropertySignature | tsm.MethodSignature)[] {
  return t.getProperties().map((p) => {
    const node = p.getDeclarations()[0] as tsm.PropertySignature | tsm.MethodSignature
    return node
  })
}

jasonkuhrt avatar Nov 13 '20 03:11 jasonkuhrt

Realizing that this topic might be a bit more nuanced than simply checking for common properties. We probably would want to check also that the types of the common property do not overlap.

https://github.com/jasonkuhrt/tydoc/issues/48#issue-742422962

jasonkuhrt avatar Nov 13 '20 12:11 jasonkuhrt

Yeah, it would be nice to add this, but not sure the best way.

Just looking at the compiler code and it seems like there are isDiscriminantProperty and findDiscriminantProperties functions in checker.ts and the logic could be copied from there. Kind of wish there was a way in the compiler api for it to point out these properties, but I don't see anything.

To add to what you've done there, I think you need to also ensure the type of the property is a literal type and not something general like a string or number.

dsherret avatar Nov 19 '20 01:11 dsherret

Just looking at the compiler code and it seems like there are isDiscriminantProperty and findDiscriminantProperties functions in checker.ts and the logic could be copied from there. Kind of wish there was a way in the compiler api for it to point out these properties, but I don't see anything.

Hm, I searched for those functions just now but didn't find anything?

jasonkuhrt avatar Nov 19 '20 01:11 jasonkuhrt

GitHub's search doesn't find results in files that are too large to display - which includes checker.ts https://github.com/microsoft/TypeScript/blob/master/src/compiler/checker.ts

Gerrit0 avatar Nov 19 '20 01:11 Gerrit0