import type { $IntentionalAny } from './types'; type PathToProp = Array; export type PointerMeta = { root: {}; path: (string | number)[]; }; export type UnindexableTypesForPointer = number | string | boolean | null | void | undefined | Function; export type UnindexablePointer = { [K in $IntentionalAny]: Pointer; }; /** * A wrapper type for the type a `Pointer` points to. */ export type PointerType = { /** * Only accessible via the type system. * This is a helper for getting the underlying pointer type * via the type space. */ $$__pointer_type: O; }; /** * The type of {@link Atom} pointers. See {@link pointer|pointer()} for an * explanation of pointers. * * @see Atom * * @remarks * The Pointer type is quite tricky because it doesn't play well with `any` and other inexact types. * Here is an example that one would expect to work, but currently doesn't: * ```ts * declare function expectAnyPointer(pointer: Pointer): void * * expectAnyPointer(null as Pointer<{}>) // this shows as a type error because Pointer<{}> is not assignable to Pointer, even though it should * ``` * * The current solution is to just avoid using `any` with pointer-related code (or type-test it well). * But if you enjoy solving typescript puzzles, consider fixing this :) * Potentially, [TypeScript variance annotations in 4.7+](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#optional-variance-annotations-for-type-parameters) * might be able to help us. */ export type Pointer = PointerType & PointerInner, undefined extends O ? undefined : never>; type PointerInner = O extends UnindexableTypesForPointer ? UnindexablePointer : unknown extends O ? UnindexablePointer : O extends (infer T)[] ? Pointer[] : O extends {} ? { [K in keyof O]-?: Pointer; } : UnindexablePointer; /** * Returns the metadata associated with the pointer. Usually the root object and * the path. * * @param p - The pointer. */ export declare const getPointerMeta: <_>(p: PointerType<_>) => PointerMeta; /** * Returns the root object and the path of the pointer. * * @example * ```ts * const {root, path} = getPointerParts(pointer) * ``` * * @param p - The pointer. * * @returns An object with two properties: `root`-the root object or the pointer, and `path`-the path of the pointer. `path` is an array of the property-chain. */ export declare const getPointerParts: <_>(p: Pointer<_>) => { root: {}; path: PathToProp; }; /** * Creates a pointer to a (nested) property of an {@link Atom}. * * @remarks * Pointers are used to make prisms of properties or nested properties of * {@link Atom|Atoms}. * * Pointers also allow easy construction of new pointers pointing to nested members * of the root object, by simply using property chaining. E.g. `somePointer.a.b` will * create a new pointer that has `'a'` and `'b'` added to the path of `somePointer`. * * @example * ```ts * // Here, sum is a prism that updates whenever the a or b prop of someAtom does. * const sum = prism(() => { * return val(pointer({root: someAtom, path: ['a']})) + val(pointer({root: someAtom, path: ['b']})); * }); * * // Note, atoms have a convenience Atom.pointer property that points to the root, * // which you would normally use in this situation. * const sum = prism(() => { * return val(someAtom.pointer.a) + val(someAtom.pointer.b); * }); * ``` * * @param args - The pointer parameters. * * @typeParam O - The type of the value being pointed to. */ declare function pointer(args: { root: {}; path?: Array; }): Pointer; export default pointer; /** * Returns whether `p` is a pointer. */ export declare const isPointer: (p: $IntentionalAny) => p is Pointer; //# sourceMappingURL=pointer.d.ts.map