A collection of assorted type utilities for Typescript.
Last active
December 13, 2021 02:47
-
-
Save tkburns/23e58e6b1d4db1a5fbd6a7444a1c307c to your computer and use it in GitHub Desktop.
Assorted type utilities for Typescript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type MapByType<Ts extends { type: string }> = { | |
[K in Ts['type']]: Extract<Ts, { type: K }>; | |
}; | |
export type UnionToIntersection<T> = | |
(T extends unknown ? (x: T) => unknown : never) extends | |
(x: infer R) => unknown ? R : never; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { UnionToIntersection } from './01-misc'; | |
export type Head<L extends unknown[]> = | |
L extends [infer H, ...unknown[]] ? H : // tuple with >= 1 element | |
L extends [] ? never : // empty tuple | |
L[number] | undefined; // list with unknown length (eg x[]) | |
export type Tail<L extends unknown[]> = | |
L extends [head: unknown, ...tail: infer T] ? T : // tuple with >= 1 element | |
L extends [] ? [] : // empty tuple | |
L; // list with unknown length (eg x[]) | |
export type Last<L extends unknown[]> = | |
L extends Tail<L> ? (L[number] | undefined) : // list of unknown length (not a tuple) | |
L extends [] ? never : // empty tuple | |
L extends [unknown] ? Head<L> : // 1-element tuple | |
Last<Tail<L>>; // tuple with >= 2 elements | |
export type Prepend<L extends unknown[], T> = [T, ...L]; | |
export type Concat<L extends unknown[], M extends unknown[]> = | |
L extends [] ? M : // empty tuple | |
L extends Tail<L> ? (L[number] | M[number])[] : // list of unknown length (not a tuple) | |
[Head<L>, ...Concat<Tail<L>, M>]; // tuple with >= 2 elements | |
/* | |
(wip) returns a tuple type that is assignable to all unions in the provided type | |
SatisfyAll<[string, {a: 'a'}] | [string, {b: 'b'}]> ~= [string, {a: 'a'} & {b: 'b'}] | |
Note - this does not handle the case when one type in the union is a subtype of another (the union immediately swallows the subtype) | |
*/ | |
export type SatisfyAll<L extends unknown[]> = | |
[L] extends [Tail<L>] ? L[number][] : | |
[L] extends [[]] ? never : | |
[UnionToIntersection<Exclude<Head<L>, undefined>>, ...SatisfyAll<Tail<L>>]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment