shades
Version:
Lens-like functionality with a lodash-style interface.
122 lines (103 loc) • 2.99 kB
text/typescript
// Minimum TypeScript Version: 3.4
// prettier-ignore
export type Functor<F, A, B> =
F extends A[] ? B[] :
F extends { [key: string]: A } ? { [key: string]: B } :
F extends Set<A> ? Set<B> :
F extends Map<infer K, A> ? Map<K, B> :
F extends Promise<A> ? Promise<B> :
never;
// prettier-ignore
export type Unpack<F> =
F extends Array<infer A> ? A :
F extends Set<infer A> ? A :
F extends Map<any, infer A> ? A :
F extends Promise<infer A> ? A :
F extends { [n: string]: infer A } ? A :
F extends { [n: number]: infer A } ? A :
F extends Record<string, infer A> ? A :
F extends Record<number, infer A> ? A :
F extends Record<symbol, infer A> ? A :
never;
export type HasKey<K extends string, V = any> =
| { [_ in K]: V }
| { [_ in K]?: V | undefined };
export interface ErrorCannotLensIntoOptionalKey<T, K> {
error: 'You have tried to lens through an optional key. Consider using `fill` to provide defaults to your object';
_val: T;
_key: K;
}
// prettier-ignore
export type KeyAt<T, K extends string> =
[T] extends [undefined] ? undefined:
[T] extends [null] ? null :
[T] extends [{ [_ in K]: any }] ? T[K] :
[T] extends [{ [_ in K]?: any }] ? T[K] :
ErrorCannotLensIntoOptionalKey<T, K>;
export type Collection<V, K = any> =
| V[]
| { [key: string]: V }
| Map<K, V>
| Set<V>;
export type Container<V, K = any> = Collection<V, K> | Promise<V>;
export type Indexable<V = any> = V[] | Map<number, V>;
export type Index<C> = C extends Indexable<infer V> ? V : never;
export type InputType<F, Return = any> = F extends (arg: infer A) => Return
? A
: never;
export type HasPattern<Pattern> = {
[K in keyof Pattern]:
| Pattern[K]
| InputType<Pattern[K]>
| (Pattern[K] extends (a: any) => any ? never : HasPattern<Pattern[K]>)
};
export type FillingPattern<Pattern> = {
[K in keyof Pattern]?: Pattern[K] | FillingPattern<Pattern[K]>
};
export type Fill<T extends FillingPattern<P>, P> = {
[K in Exclude<keyof T, keyof P>]: T[K]
} &
{ [K in keyof P]: P[K] };
export type Fn0<Out> = () => Out;
export type Fn1<A, Out> = (a: A) => Out;
export type Fn2<A, B, Out> = (a: A, b: B) => Out;
export type Fn3<A, B, C, Out> = (a: A, b: B, c: C) => Out;
export type Fn4<A, B, C, D, Out> = (a: A, b: B, c: C, d: D) => Out;
export type Fn5<A, B, C, D, E, Out> = (a: A, b: B, c: C, d: D, e: E) => Out;
export type Fn6<A, B, C, D, E, F, Out> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F
) => Out;
export type Fn7<A, B, C, D, E, F, G, Out> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G
) => Out;
export type Fn8<A, B, C, D, E, F, G, H, Out> = (
a: A,
b: B,
c: C,
d: D,
e: E,
f: F,
g: G,
h: H
) => Out;
export interface Traversal<Item> {
get(s: Collection<Item>): Collection<Item>;
mod(f: (a: Item) => Item): (s: Collection<Item>) => Collection<Item>;
traversal?: true;
}
export interface Lens<S, A> {
get(s: S): A;
mod(f: (a: A) => A): (s: S) => S;
traversal?: false;
}