Skip to content

Commit

Permalink
Add UnionToTuple type
Browse files Browse the repository at this point in the history
  • Loading branch information
kopach committed Nov 22, 2023
1 parent 2c39d54 commit f1cad77
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export type {WritableKeysOf} from './source/writable-keys-of';
export type {HasWritableKeys} from './source/has-writable-keys';
export type {Spread} from './source/spread';
export type {TupleToUnion} from './source/tuple-to-union';
export type {UnionToTuple} from './source/union-to-tuple';
export type {IntRange} from './source/int-range';
export type {IsEqual} from './source/is-equal';
export type {
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
- [`MultidimensionalReadonlyArray`](source/multidimensional-readonly-array.d.ts) - Create a type that represents a multidimensional readonly array of the given type and dimensions.
- [`ReadonlyTuple`](source/readonly-tuple.d.ts) - Create a type that represents a read-only tuple of the given type and length.
- [`TupleToUnion`](source/tuple-to-union.d.ts) - Convert a tuple/array into a union type of its elements.
- [`UnionToTuple`](source/union-to-tuple.d.ts) - Convert a union type into a tuple type of its elements.

### Numeric

Expand Down
30 changes: 30 additions & 0 deletions source/union-to-tuple.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type {UnionToIntersection} from './union-to-intersection';

/**
Convert a union type into a tuple/array type of its elements.
This can be useful when you have objects with a finite set of keys and want a type defining only the allowed keys, but do not want to repeat yourself.
@example
```
const pets = {
dog: '🐶',
cat: '🐱',
snake: '🐍',
};
type Pet = keyof typeof pets;
//=> "dog" | "cat" | "snake"
const petList = Object.keys(pets) as UnionToTuple<Pet>;
//=> ["dog", "cat", "snake"]
```
@category Array
*/

export type UnionToTuple<Tuple> = UnionToIntersection<
Tuple extends never ? never : (_: Tuple) => Tuple
> extends (_: never) => infer LastTupleElement
? [...UnionToTuple<Exclude<Tuple, LastTupleElement>>, LastTupleElement]
: [];
12 changes: 12 additions & 0 deletions test-d/union-to-tuple.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {expectAssignable, expectError, expectType} from 'tsd';
import type {UnionToTuple} from '../index';

type Options = UnionToTuple<'a' | 'b' | 'c'>;

const options: Options = ['a', 'b', 'c'];

expectAssignable<Options>(options);
expectType<'a'>(options[0]);
expectType<'b'>(options[1]);
expectType<'c'>(options[2]);
expectError(options[0] = 'b');

0 comments on commit f1cad77

Please sign in to comment.