diff --git a/README.md b/README.md index 3fa9ff4..9cb50c6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1251 TILs and counting..._ +_1252 TILs and counting..._ --- @@ -69,6 +69,7 @@ _1251 TILs and counting..._ * [Workflow](#workflow) * [XState](#xstate) * [YAML](#yaml) +* [Zod](#zod) --- @@ -1480,6 +1481,10 @@ _1251 TILs and counting..._ - [Create Multi-Line Strings Without The Line Breaks](yaml/create-multi-line-strings-without-the-line-breaks.md) - [YAML Is A Superset Of JSON](yaml/yaml-is-a-superset-of-json.md) +### Zod + +- [Create Union Type Of Nearly Identical Objects](zod/create-union-type-of-nearly-identical-objects.md) + ## Usage The `.vimrc` file for this project contains a function `CountTILs` that can diff --git a/zod/create-union-type-of-nearly-identical-objects.md b/zod/create-union-type-of-nearly-identical-objects.md new file mode 100644 index 0000000..39e9dce --- /dev/null +++ b/zod/create-union-type-of-nearly-identical-objects.md @@ -0,0 +1,48 @@ +# Create Union Type Of Nearly Identical Objects + +Let's say I have a data layer that can return data in two nearly identical +shapes. Either shape has all of the same keys except one has an `_id` key and +the other has a `key` key. I want a Zod schema that can validate either of +these shapes and produce a union type. + +Let's start with an intermediate Zod object that holds all possible keys. + +```typescript +const intermediateObject = z.object({ + _id: z.string(), + key: z.string(), + name: z.string(), + age: z.number() + // any other shared keys +}) +``` + +I can then manipulate this into the desired schema using +[`or()`](https://github.com/colinhacks/zod#unions) and +[`omit()`](https://github.com/colinhacks/zod#pickomit). + +```typescript +const objectWithoutId = intermediateObject.omit({ _id: true }) +const objectWithoutKey = intermediateObject.omit({ key: true }) + +const unionSchema = objectWithoutId.or(objectWithoutKey) +``` + +And this produces the schema and union type I was looking for: + +```typescript +type Union = z.infer; +/* +type Union = { + key: string; + name: string; + age: number; +} | { + _id: string; + name: string; + age: number; +} +*/ +``` + +[source](https://twitter.com/jbrancha/status/1572357904266850305)