PatrickP
Convex Community4mo ago
6 replies
Patrick

Intersection of Discriminated Unions

First of all, I love Convex - great job team ❤️

I have a use case where I need to create a convex schema that is an intersection of two discriminated unions. I have the following toy example that works with Zod but I can't see an easy way of implementing the same behavior using Convex.

In the example below we start with two unions:
1. People vs animals
2. Countries vs cities

Ideally, in convex, I would be able to easily define the intersection of those two, allowing me to store objects like this:

{
  entityType: "animal",
  species: "dog",
  locationType: "city",
  locationName: "New York",
}


I know I can write a function to get all NxM possible convex objects, but I was just wondering if there is cleaner approach, similar to what I can do with Zod

import { z } from "zod";

// person vs animal discriminated union
const person = z.object({
  entityType: z.literal("person"),
  personName: z.string(),
  age: z.number(),
});

const animal = z.object({
  entityType: z.literal("animal"),
  species: z.string(),
});

const personOrAnimal = z.union([person, animal]);

const examplePersonOrAnimal: z.infer<typeof personOrAnimal> = {
  entityType: "animal",
  species: "dog",
};

// location discriminated union
const country = z.object({
  locationType: z.literal("country"),
  locationName: z.string(),
});

const city = z.object({
  locationType: z.literal("city"),
  locationName: z.string(),
});

const location = z.union([country, city]);

const exampleLocation: z.infer<typeof location> = {
  locationType: "city",
  locationName: "New York",
};

// combined NxN union
const entityAtLocation = z.intersection(personOrAnimal, location);

const exampleEntityAtLocation: z.infer<typeof entityAtLocation> = {
  entityType: "animal",
  species: "dog",
  locationType: "city",
  locationName: "New York",
};
Was this page helpful?