/** * Returns number in case `T` is an `Array`, * else if `T extends Record`, it returns the keys of it, * else it returns never. */ export type ToKeys = T extends Array ? number : T extends Record ? { [K in keyof T]: K; }[keyof T] : never; /** * Return type of the pick function. */ export type PickReturn> = T extends Array ? A | undefined : T extends Record ? K extends keyof T ? T[K] | undefined : never : undefined; /** * Takes a value `T` and a key `K`. * If value is an `Array` (`K` is enforced as number in this case), it returns `value[key]` as `A | undefined`. * If value is a `Record` (`K` is enforced as `keyof T` in this case), it returns `value[key]` as `T[K] | undefined`. * Else it returns undefined. */ export declare const pick: >(value: T | undefined, key: K) => PickReturn; /** * An `OptionalLens` grants type-safe access on potential `P`, hence it can be used to * get `P | undefined` from an arbitrary `T`, where `T` might be a union of arbitrary types. * * From an `OptionalLens`, you can also retrieve a new `OptionalLens`, where K is a potential key of P. * Use `getLens()` to get an initial `OptionalLens`. * * You can see `OptionalLens` as "universal optional chaining". While normal optional chaining only works on a `T | null | undefined`, * the `OptionalLens` allows the type-safe access on arbitrary unions. * * E.g. given the following type and values: * ```ts * type TestChild = boolean | { x: number | Array }; * type Test = * | number * | { * a: string | Array; * }; * * const t1: Test = 42; * const t2: Test = { a: 'Test3' }; * const t3: Test = { a: [true, { x: 7 }, { x: [1, 2, 3] }] }; * const t4: TestChild = { x: 7 }; * ``` * * you could get the following results with optional-lenses: * ```ts * const lensA = getLens().k('a'); * const a1 = lensA.get(t1); // => undefined (inferred as undefined | string | Array) * const a2 = lensA.get(t2); // => 'Test3' (inferred as undefined | string | Array) * const a3 = lensA.get(t3); // => [true, { x: 7 }, { x: [1, 2, 3] }] (inferred as undefined | string | Array) * * const lensA2X1 = lensA.k(2).k('x').k(1); * const n1 = lensA2X1.get(t1); // => undefined (inferred as number | undefined) * const n2 = lensA2X1.get(t2); // => undefined (inferred as number | undefined) * const n3 = lensA2X1.get(t3); // => 2 (inferred as number | undefined) * * const lensB = getLens().compose(getLens()); * const t3a = lensB.k('a').get(t3); // [true, { x: 7 }, { x: [1, 2, 3] }] (inferred as undefined | string | Array) * const t4x = lensB.k('x').get(t4); // 7 (inferred as undefined | number | Array) * ``` */ export type OptionalLens = { get: (value: T) => P | undefined; k: >(key: K) => OptionalLens>; compose: (lens: OptionalLens) => OptionalLens; }; /** * Typeguard to check, if the given value is an {@link OptionalLens} */ export declare const isOptionalLens: (value: any) => value is OptionalLens; /** * Get an `OptionalLens` for type-safe access on arbitrarily nested properties of type `T`, * where `T` might be a union of arbitrary types. * * Given the following type and values: * ```ts * type TestChild = boolean | { x: number | Array }; * type Test = * | number * | { * a: string | Array; * }; * * const t1: Test = 42; * const t2: Test = { a: 'Test3' }; * const t3: Test = { a: [true, { x: 7 }, { x: [1, 2, 3] }] }; * const t4: TestChild = { x: 7 }; * ``` * * you could get the following results with optional-lenses: * ```ts * const lensA = getLens().k('a'); * const a1 = lensA.get(t1); // => undefined (inferred as undefined | string | Array) * const a2 = lensA.get(t2); // => 'Test3' (inferred as undefined | string | Array) * const a3 = lensA.get(t3); // => [true, { x: 7 }, { x: [1, 2, 3] }] (inferred as undefined | string | Array) * * const lensA2X1 = lensA.k(2).k('x').k(1); * const n1 = lensA2X1.get(t1); // => undefined (inferred as number | undefined) * const n2 = lensA2X1.get(t2); // => undefined (inferred as number | undefined) * const n3 = lensA2X1.get(t3); // => 2 (inferred as number | undefined) * * const lensB = getLens().compose(getLens()); * const t3a = lensB.k('a').get(t3); // [true, { x: 7 }, { x: [1, 2, 3] }] (inferred as undefined | string | Array) * const t4x = lensB.k('x').get(t4); // 7 (inferred as undefined | number | Array) * ``` */ export declare const getLens: () => OptionalLens; /** * Get a concrete `OptionalLens` from an `OptionalLens` (or never, if L is no `OptionalLens`) */ export type ToLensType = [L] extends [OptionalLens] ? OptionalLens : never; /** * Get a concrete `T` from an `OptionalLens` (or never, if L is no `OptionalLens`) */ export type ToLensInputType = [L] extends [OptionalLens] ? T : never; /** * Get a concrete `T` from an `OptionalLens` (or never, if L is no `OptionalLens`) */ export type ToLensOutputType = [L] extends [OptionalLens] ? T : never; /** * Get `T`, if `VL` is an `OptionalLens`, else get `OptionalLens` */ export type ValueOrLens = [VL] extends [OptionalLens] ? ToLensInputType : OptionalLens; /** * Get return type of `OptionalLens::get(T)`, if `X` is an `OptionalLens`, * else get the return type of `OptionalLens::get(T)`, if `Y` is an `OptionalLens`, * else never. */ export type FromLensReturn = [X] extends [OptionalLens] ? ToLensOutputType | undefined : [Y] extends [OptionalLens] ? ToLensOutputType | undefined : never; /** * Utility function to apply an `OptionalLens` to a `T` */ export declare const fromValueAndLens: (value: T) => >(lens: L) => ToLensOutputType | undefined; /** * Utility function to apply a `T` to an `OptionalLens` */ export declare const fromLensAndValue: >(lens: L) => >(value: T) => ToLensOutputType | undefined; /** * If the first argument is an `OptionalLens`, this function behaves like `fromLensAndValue`, * else it behaves like `fromValueAndLens` */ export declare const fromLens: (valueOrLens1: X) => >(valueOrLens2: Y) => FromLensReturn; /** * Return type of the toGetter function. * Like {@link OptionalLens}, a `Getter` can be used for optional chaining on arbitrary union types. * In contrast to {@link OptionalLens}, the initial `Getter` must be obtained from a value of type `T`. * You can thus use it as kind of ad-hoc lens for a one-time access. In most cases however, * using an {@link OptionalLens} is the better choice. * * See `toGetter` documentation for example usage. */ export type Getter = { get: () => T; k: >(key: K) => Getter>; }; /** * Helper type to infer the concrete value type `T` wrapped by a `Getter` */ export type ToGetterValue = T extends Getter ? V : never; /** * Wraps the given value of type T in a `Getter`. * A `Getter` can be used like a one-time ad-hoc version of an {@link OptionalLens}. * In most cases however, using an {@link OptionalLens} is the better choice. * * Given the following type and values: * ```ts * type Test = * | number * | { * x: Array; * a: { * b: number; * }; * | { * a: { * b: string; * } * } * }; * * let t1: Test = 42; * let t2: Test = { x: [1, 2, 3] }; * let t3: Test = { a: { b: 'Test' } }; * ``` * * you could get the following results with toGetter: * ```ts * const b1 = toGetter(t1).k('a').k('b').get(); // => undefined (inferred as number | string | undefined) * const b2 = toGetter(t2).k('a').k('b').get(); // => undefined (inferred as number | string | undefined) * const b3 = toGetter(t3).k('a').k('b').get(); // => 'Test' (inferred as number | string | undefined) * const x1 = toGetter(t1).k('x').k(1).get(); // => undefined (inferred as number | undefined) * const x2 = toGetter(t2).k('x').k(1).get(); // => 2 (inferred as number | undefined) * const x3 = toGetter(t3).k('x').k(1).get(); // => undefined (inferred as number | undefined) * ``` */ export declare const toGetter: (value: T) => Getter;