-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Union of unions #13
Comments
Hi. Unfortunately, I don't believe this to be possible inside TypeBox without creating a circular type reference when conditionally mapping, which TypeScript currently forbids. Note that the types To work around this, you infer explicitly, as follows. const X = Type.Union([ Type.Number() ])
const Y = Type.Union([ Type.String() ])
const Z = Type.Union([ Type.Boolean() ])
const W = Type.Union([X, Y, Z])
// ... instead of
type W = Static<typeof W> // -> any
// ... try
type W = Static<typeof X | typeof Y | typeof Z> // -> number | string | boolean Hope that helps |
Perfect this works. Thanks for the quick help ❤ |
heyho, I just bumped into the same problem. I was wondering if there's a more elegant solution to this? In io-ts this works: import * as t from 'io-ts';
const unionA = t.union([t.number, t.string]);
const unionB = t.union([t.boolean, t.number]);
const unionC = t.union([unionA, unionB]);
type UnionC = t.TypeOf<typeof unionC> // -> string | number | boolean Either way I think if typebox cannot support this at all I think we should put a hint about this limitation into the docs. I first thought something's wrong with my business model and it took me a quite a while to realize that nesting unions or intersections simply doesn't work in typebox :) |
@geekflyer Heya, I haven't spent a lot of time looking at how io-ts does its thing to be honest, but if they have figured out a way of working through the recursive problem outlined above, id certainly be interested in exploring their approach. Will reopen this issue for further discussion. PR's also welcome :) |
I've generated types for larger unions of size 20: https://gist.github.com/matomesc/d512b21288c21d0625b8982db38fc117 |
in my project we're using meanwhile a custom combinator called import { mergeAll } from "remeda";
/*
Here we want to intersect the types of `properties` prop as the result of merge, so that
when converted to static types it includes all the fields.
Since we pass in an array, type of our T["properties"] is an union of `properties` such as:
{ x: TString} | { y: TNumber } | { z: TBoolean }
First we convert this union to an intersection using the property defined as this in TS handbook:
"[...] multiple candidates for the same type variable in contra-variant positions
causes an intersection type to be inferred"
Then we have to tell the compiler that our intersection actually extends TProperties, which we do
by using a `Cast` utility type
*/
type UnionToIntersection<U> = (U extends TProperties ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type Cast<T, K> = T extends K ? T : K;
export function mergeObjectSchemas<T extends TObject<TProperties> | TMap<UserDefinedOptions>>(
schemas: T[],
options?: UserDefinedOptions
): TObject<Cast<UnionToIntersection<T["properties"]>, TProperties>> {
return {
...options,
type: "object",
properties: mergeAll(schemas.map(schema => schema.properties)) as T["properties"],
required: schemas.flatMap(schema => schema.required ?? [])
};
} this can be used in the same way as |
Nice solution and I think this approach can be used for merging unions as well. Also I noticed that the |
@sinclairzx81 adding the patch for large unions slows the compiler down significantly (5x in my case for 77 unions in a small 2k LOC project). I'm not sure why this is happening - I'm not familiar with debugging the compiler. Perhaps the TypeScript team can shed some light into why the union types kill performance. Edit: it's both unions and tuples and the larger they are the slower the compiler. |
It'd say that's not entirely unexpected. The thing is with that large patch TypeScript has a zillion candidate type combinations to tests for, with many inferred type parameters. |
Some options may exist in TS 4.0 to get rid of those composite variants. For review. |
Performance issues, including large unions, are fixed in TS 4.0.0-beta 🎉 |
Hi, it it possible to create a union of unions?
I tried doing the following
but the static type is
any
.My use case is a large union that I would like to break up into smaller unions. I suppose that increase the union size from 8 can also work but I'd rather compose the smaller unions.
The text was updated successfully, but these errors were encountered: