libfun
Version:
Make functional programming fun!
91 lines (81 loc) • 2.08 kB
text/typescript
/** Combines deduplicated arrays without any new duplicates */
type Combine<A extends readonly any[], B extends readonly any[]> = A extends [
...infer S,
infer L
]
? Equal<L, B[0], Combine<S, B>, [...A, ...B]>
: B;
/** Checks whether two types are equal to each other */
type Equal<A, B, True = true, False = false> = A extends B
? B extends A
? True
: False
: False;
/** Checks whether the value is a tuple or an array */
type IsTuple<T, True = true, False = false> = IsNever<
T,
False,
T extends readonly [any, ...any] ? True : T extends [] ? True : False
>;
/** Checks whether the type `T` is equal to `never` */
type IsNever<T, True = true, False = false> = [T] extends [never]
? True
: False;
/** Returns a flat type of any array/tuple/iterable */
type Flatten<T> = IsTuple<
T,
T extends readonly [infer U, ...infer Tail extends any[]]
? U extends readonly any[]
? Flatten<U>
: U | Flatten<Tail>
: never,
T extends string
? T
: T extends Iterable<infer U>
? U extends Iterable<infer R>
? Flatten<R>
: U
: T
>;
/** Returns the type of the last element of an array or tuple */
type Last<T extends any[]> = IsTuple<T> extends true
? T extends [...any[], infer L]
? L
: never
: T extends (infer L)[]
? L
: never;
/** Function shorthand */
type Fn<A = any[], Z = any> = (...args: A extends any[] ? A : [A]) => Z;
/** Checks whether a tuple or an array contains the given type */
type Contains<
T extends readonly any[],
U,
True = true,
False = false
> = IsTuple<
T,
T extends [infer Item, ...infer Rest]
? U extends Item
? True
: Contains<Rest, U, True, False>
: False,
T extends (infer Item)[] ? (U extends Item ? True : False) : never
>;
/** Converts any union to its intersection. Eg. `A | B` to `A & B` */
type Intersected<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
export type {
Intersected,
Contains,
Combine,
IsTuple,
IsNever,
Flatten,
Equal,
Last,
Fn,
};