vue-reactivity-fantasy
Version:
Some fancy functionalities about vue reactivity
144 lines (124 loc) • 8.14 kB
TypeScript
import * as vue from 'vue';
import { Ref, ComputedRef, WritableComputedRef, DebuggerOptions, UnwrapRef, WatchOptions, ShallowRef } from 'vue';
/**
* Holds changes inside the block before the reactive context is updated
* @param fn wraps the reactive updates that should be batched
* @returns the return value from `fn`
*/
declare function batch<T>(fn: () => T): T;
/**
* Ignores tracking context inside its scope
* @param fn the scope that is out of the tracking context
* @returns the return value of `fn`
*/
declare function untrack<T>(fn: () => T): T;
declare type MaybeRef<T> = T | Ref<T>;
declare type ValueSource<T = unknown> = Ref<T> | (() => T);
declare type MaybeValueSource<T = unknown> = ValueSource<T> | T;
declare type Dependency<T = unknown> = ValueSource<T> | object;
declare type DependencyList<T = unknown> = Array<Dependency<T>>;
declare type InvalidDependency = null | undefined | string | number | boolean;
declare type ResolveValueSource<T> = T extends ValueSource<infer R> ? R : T;
declare type ResolveDependencySource<T> = T extends any[] ? {
[K in keyof T]: ResolveDependencySource<T[K]>;
} : ResolveValueSource<T>;
interface UseBooleanControl {
set: (value: boolean) => void;
setTrue: () => void;
setFalse: () => void;
toggle: () => void;
}
declare function useBoolean(initialValue?: MaybeRef<boolean>): [Ref<boolean>, UseBooleanControl];
declare function useComputed<T>(source: ValueSource<T>): ComputedRef<T>;
declare function useComputed<T>(source: ValueSource<T>, setter: (value: T) => void): WritableComputedRef<T>;
declare function useComputed<T>(source: ValueSource<T>, debugOptions: DebuggerOptions): ComputedRef<T>;
declare function useDerivedState<T, Props>(props: ValueSource<Props>, getDerivedStateFromProps: (props: Props, prevState: T | undefined) => T): ComputedRef<T>;
declare type Cleanup = () => void;
declare type OnCleanup = (cleanup: Cleanup) => void;
declare type SetupEffect = (onCleanup: OnCleanup) => void | Cleanup;
interface ManualEffectControl {
clear: () => void;
ensure: () => void;
reset: (setup?: SetupEffect) => void;
}
declare function createManualEffect(setup?: SetupEffect, immediate?: boolean): ManualEffectControl;
interface ToggleControl<T> {
set: (value: T) => void;
setDefault: () => void;
setReverse: () => void;
toggle: () => void;
}
/**
* A development pattern used to reduce the focus on how default value and reverse value provide.
*/
declare function createToggleControl<T, U>(value: Ref<T | U>, defaultValue: ValueSource<T>, reverseValue: ValueSource<U>): ToggleControl<T | U> & {
value: Ref<T | U>;
};
declare function isWritableRef<T = unknown>(v: unknown): v is Ref<UnwrapRef<T>>;
declare function isValidDependency<T = unknown>(dep: unknown): dep is Dependency<T> | DependencyList<T>;
declare function resolveSourceValue<T>(source: MaybeValueSource<T>): T;
declare function resolveSourceValueGetter<T>(source: MaybeValueSource<T>): () => T;
declare function resolveComputed<T>(source: MaybeValueSource<T>): vue.ComputedRef<T>;
declare type SetupEffectWithDependency<V, LV> = (onCleanup: OnCleanup, dependency: V, lastDependency: LV) => void | Cleanup;
declare type EffectDependency<T = unknown> = Dependency<T> | DependencyList<T>;
declare type StopEffect = () => void;
interface UseEffectOptions<Immediate extends boolean = false> extends WatchOptions<Immediate> {
}
/**
* Accepts a function that contains imperative, possibly effectful code.
*
* To cope with multiple scenarios, it has the following logic:
* 1. If you pass in valid dependency,
* `setup` will only rerun when one of the dependencies has changed.
*
* 2. If you don't pass in valid dependency,
* `setup` will rerun on the side effects carried by setup.
*
* 3. If source is a getter function, it can receive changes to dependency.
*/
declare function useEffect<T extends DependencyList, Immediate extends Readonly<boolean> = false>(setup: SetupEffectWithDependency<ResolveDependencySource<T>, ResolveDependencySource<Immediate extends true ? T | undefined : T>>, dependencies: [...T], options?: UseEffectOptions<Immediate>): StopEffect;
declare function useEffect<T extends EffectDependency, Immediate extends Readonly<boolean> = false>(setup: SetupEffectWithDependency<ResolveDependencySource<T>, ResolveDependencySource<Immediate extends true ? T | undefined : T>>, dependency: T, options?: UseEffectOptions<Immediate>): StopEffect;
declare function useEffect<T extends InvalidDependency>(setup: SetupEffect, dependency?: T, options?: Omit<UseEffectOptions, 'immediate'>): StopEffect;
interface UseFollowStateOptions {
immediate?: boolean;
deep?: boolean;
onFollow?: () => void;
}
declare function useFollowState<T>(initialValue: T | Ref<T>, target: ValueSource<T>, options?: UseFollowStateOptions): [Ref<T>, () => void];
/**
* @returns [track, trigger]
*/
declare function useForceUpdate(): [() => number, () => void];
interface UseMemoOptions {
deep?: boolean;
}
/**
* `useMemo` will cache the value parsed from the `source` and "trigger" only when the value changes.
*
* To cope with multiple scenarios, it has the following logic:
* 1. If you pass in valid dependency,
* `useMemo` will only recompute the memoized value when one of the dependencies has changed.
*
* 2. If you don't pass in valid dependency,
* `useMemo` value will depend on the side effects carried by source.
*
* 3. If source is a getter function, it can receive changes to dependency.
*/
declare function useMemo<T, D extends any[] = any[]>(source: Exclude<ValueSource<T>, Function> | ((dependency: ResolveDependencySource<D>, lastDependency: ResolveDependencySource<D> | undefined) => T), dependencies: [...D], options?: UseMemoOptions): ComputedRef<T>;
declare function useMemo<T, D extends Dependency | DependencyList = Dependency | DependencyList>(source: Exclude<ValueSource<T>, Function> | ((dependency: ResolveDependencySource<D>, lastDependency: ResolveDependencySource<D> | undefined) => T), dependency: D, options?: UseMemoOptions): ComputedRef<T>;
declare function useMemo<T, D extends InvalidDependency = InvalidDependency>(source: ValueSource<T>, dependency?: D): ComputedRef<T>;
declare type MergedState<Value, DefaultValue> = undefined extends Value ? undefined extends DefaultValue ? Value | DefaultValue : DefaultValue : Value;
/**
* Use the merged value of two values, its priority is
* 1. if `source` is not undefined, the value of `source` is used
* 2. if `source` is undefined, the value of `defaultValue` is used
*/
declare function useMergedState<T, U>(source: MaybeValueSource<T>, defaultValue?: MaybeValueSource<U>): ComputedRef<MergedState<T, U>>;
declare function useState<T, Shallow extends Readonly<boolean> = false>(initialValue: MaybeValueSource<T>, shallow?: Shallow): [Shallow extends true ? ShallowRef<T> : Ref<T>, (value: T) => void];
declare function useToggle(defaultValue?: MaybeValueSource<any>): [Ref<boolean>, ToggleControl<boolean>];
declare function useToggle<T, U>(defaultValue: MaybeValueSource<T>, reverseValue: MaybeValueSource<U>): [Ref<T | U>, ToggleControl<T | U>];
/**
* Resolve the source value, and convert it through a transform function.
*/
declare function useTransformState<T, Source>(source: MaybeValueSource<Source>, transform: (source: Source) => T): ComputedRef<T>;
export { Cleanup, Dependency, DependencyList, EffectDependency, InvalidDependency, ManualEffectControl, MaybeRef, MaybeValueSource, MergedState, OnCleanup, ResolveDependencySource, ResolveValueSource, SetupEffect, SetupEffectWithDependency, StopEffect, ToggleControl, UseBooleanControl, UseEffectOptions, UseFollowStateOptions, UseMemoOptions, ValueSource, batch, createManualEffect, createToggleControl, isValidDependency, isWritableRef, resolveComputed, resolveSourceValue, resolveSourceValueGetter, untrack, useBoolean, useComputed, useDerivedState, useEffect, useFollowState, useForceUpdate, useMemo, useMergedState, useState, useToggle, useTransformState };