type-fest icon indicating copy to clipboard operation
type-fest copied to clipboard

Add type for union joins

Open roydukkey opened this issue 2 years ago • 2 comments

For example, this would be useful for a FontStyle type where the possible values are the space separated string of the terms bold, italic, underline, and strikethrough.

Here a possibility, but it seems this could be improved.

import type { UnionToIntersection } from 'type-fest';

type UnionToOvlds<U> = UnionToIntersection<U extends unknown ? (f: U) => void : never>;
type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;
type UnionConcat<U extends string, Sep extends string> = PopUnion<U> extends infer SELF
	? SELF extends string
		? Exclude<U, SELF> extends never
			? SELF
			: `${UnionConcat<Exclude<U, SELF>, Sep>}${Sep}${SELF}` | UnionConcat<Exclude<U, SELF>, Sep> | SELF
		: never
	: never;

type FontStyle = UnionConcat<'bold' | 'italic' | 'underline' | 'strikethrough', ' '>;
	// "bold" | "italic" | "underline" | "strikethrough" | "bold italic" | "bold underline" |
	// "italic underline" | "bold italic underline" | "bold strikethrough" | "italic strikethrough" |
	// ... 4 more ... | "bold italic underline strikethrough"

Also, I'm unsure whether this should be considered a feature or not, but notice that "italic bold" is not acceptable by this type because "bold italic" is.

roydukkey avatar Apr 30 '22 14:04 roydukkey

This could easily lead to infinite permutations. Not sure it's a good idea. It's also quite niche. I think we are more likely to add the underlying utilities that enable this, rather than this exact type (for example UnionConcat).

In this specific case, it sounds like it's better to have the canonical value as a union and instead split the type of the user input into a union.

sindresorhus avatar May 06 '22 06:05 sindresorhus

Yup. That's fair. Thanks!

roydukkey avatar May 06 '22 12:05 roydukkey