Skip to content

Instantly share code, notes, and snippets.

@dfoverdx
Created July 7, 2021 18:29
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save dfoverdx/147b76a695d22e26e36097c987897d0b to your computer and use it in GitHub Desktop.
TypeScript composite `as const`
/**
* Creates a readonly object which combines the given `as const` constants. If any of the objects overlap in keys or
* values, it evaluates to `never`. Unfortunately this does not work with enums because there is no way to determine if
* the *value* `Enum1.foo` is different than that `Enum2.bar`. Typescript treats enum values as distinct types.
*
* I made this type to prevent flux action types from overlapping.
*
* Requires Typescript@4.2 or later.
*/
type CompositeAsConst<
T extends readonly Record<string, string | number>[],
C extends Record<string, string | number> = {}
> =
T['length'] extends 0
? Readonly<{ [K in keyof C]: C[K] }>
: T extends [infer Head, ...infer Tail]
? (keyof Head & keyof C) | (Head[keyof Head] & C[keyof C] & (number | string)) extends never
? Tail extends readonly Record<string, string | number>[]
? (
& { [K in keyof C]: C[K] }
& { [K in keyof Head]: Head[K] }
) extends infer Next
? Next extends Record<string, string | number>
? CompositeAsConst<Tail, Next>
: never
: never
: never
: never
: never;
/** Examples */
const Foo = {
foo: 'foo'
} as const;
const Bar = {
bar: 'bar'
} as const;
const Baz = {
baz: 'baz',
foo: 'foo'
} as const;
const Baz2 = {
baz: 'foo'
} as const;
function compositeAsConst<T extends readonly Record<string, string | number>[]>(...constants: T): CompositeAsConst<T> {
return Object.assign({}, ...constants);
}
const FooBar = compositeAsConst(Foo, Bar); // => { readonly foo: 'foo'; readonly bar: 'bar'; };
const FooBaz = compositeAsConst(Foo, Baz); // => never;
const FooBaz2 = compositeAsConst(Foo, Baz2); // => never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment