UNPKG

20.6 kBTypeScriptView Raw
1// Minimum TypeScript Version: 3.7
2
3/**
4 * Copyright (c) Facebook, Inc. and its affiliates.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 *
9 * @emails oncall+recoil
10 */
11
12/**
13 * This file is a manual translation of the flow types, which are the source of truth, so we should not introduce new terminology or behavior in this file.
14 */
15
16 export { };
17
18 import * as React from 'react';
19
20 // state.d.ts
21 type NodeKey = string;
22
23 // node.d.ts
24 export class DefaultValue {
25 private __tag: 'DefaultValue';
26 }
27
28 // recoilRoot.d.ts
29 export type RecoilRootProps = {
30 initializeState?: (mutableSnapshot: MutableSnapshot) => void,
31 override?: true,
32 children: React.ReactNode,
33 } | {
34 override: false,
35 children: React.ReactNode,
36 };
37
38 /**
39 * Root component for managing Recoil state. Most Recoil hooks should be
40 * called from a component nested in a <RecoilRoot>
41 */
42 export const RecoilRoot: React.FC<RecoilRootProps>;
43
44 // Snapshot.d.ts
45 declare const SnapshotID_OPAQUE: unique symbol;
46 export interface SnapshotID {
47 readonly [SnapshotID_OPAQUE]: true;
48 }
49
50 interface ComponentInfo {
51 name: string;
52 }
53
54 interface RecoilStateInfo<T> {
55 loadable?: Loadable<T>;
56 isActive: boolean;
57 isSet: boolean;
58 isModified: boolean; // TODO report modified selectors
59 type: 'atom' | 'selector';
60 deps: Iterable<RecoilValue<T>>;
61 subscribers: {
62 nodes: Iterable<RecoilValue<T>>,
63 components: Iterable<ComponentInfo>,
64 };
65 }
66
67 export class Snapshot {
68 getID(): SnapshotID;
69 getLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>;
70 getPromise<T>(recoilValue: RecoilValue<T>): Promise<T>;
71 getNodes_UNSTABLE(opts?: { isModified?: boolean, isInitialized?: boolean }): Iterable<RecoilValue<unknown>>;
72 getInfo_UNSTABLE<T>(recoilValue: RecoilValue<T>): RecoilStateInfo<T>;
73 map(cb: (mutableSnapshot: MutableSnapshot) => void): Snapshot;
74 asyncMap(cb: (mutableSnapshot: MutableSnapshot) => Promise<void>): Promise<Snapshot>;
75 retain(): () => void;
76 isRetained(): boolean;
77 }
78
79 export class MutableSnapshot extends Snapshot {
80 set: SetRecoilState;
81 reset: ResetRecoilState;
82 }
83
84 declare const WrappedValue_OPAQUE: unique symbol;
85 export interface WrappedValue<T> {
86 readonly [WrappedValue_OPAQUE]: true;
87 }
88
89 // Effect is called the first time a node is used with a <RecoilRoot>
90 export type AtomEffect<T> = (param: {
91 node: RecoilState<T>,
92 storeID: StoreID,
93 trigger: 'set' | 'get',
94
95 // Call synchronously to initialize value or async to change it later
96 setSelf: (param:
97 | T
98 | DefaultValue
99 | Promise<T | DefaultValue>
100 | ((param: T | DefaultValue) => T | DefaultValue),
101 ) => void,
102 resetSelf: () => void,
103
104 // Subscribe callbacks to events.
105 // Atom effect observers are called before global transaction observers
106 onSet: (
107 param: (newValue: T, oldValue: T | DefaultValue, isReset: boolean) => void,
108 ) => void,
109
110 // Accessors to read other atoms/selectors
111 getPromise: <S>(recoilValue: RecoilValue<S>) => Promise<S>,
112 getLoadable: <S>(recoilValue: RecoilValue<S>) => Loadable<S>,
113 getInfo_UNSTABLE: <S>(recoilValue: RecoilValue<S>) => RecoilStateInfo<S>,
114 }) => void | (() => void);
115
116 // atom.d.ts
117 interface AtomOptionsWithoutDefault<T> {
118 key: NodeKey;
119 effects?: ReadonlyArray<AtomEffect<T>>;
120 effects_UNSTABLE?: ReadonlyArray<AtomEffect<T>>;
121 dangerouslyAllowMutability?: boolean;
122 }
123 interface AtomOptionsWithDefault<T> extends AtomOptionsWithoutDefault<T> {
124 default: RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T> | T;
125 }
126 export type AtomOptions<T> = AtomOptionsWithoutDefault<T> | AtomOptionsWithDefault<T>;
127
128 /**
129 * Creates an atom, which represents a piece of writeable state
130 */
131 export function atom<T>(options: AtomOptions<T>): RecoilState<T>;
132 export namespace atom {
133 function value<T>(value: T): WrappedValue<T>;
134 }
135
136 export type GetRecoilValue = <T>(recoilVal: RecoilValue<T>) => T;
137 export type SetterOrUpdater<T> = (valOrUpdater: ((currVal: T) => T) | T) => void;
138 export type Resetter = () => void;
139 export interface TransactionInterface_UNSTABLE {
140 get<T>(a: RecoilValue<T>): T;
141 set<T>(s: RecoilState<T>, u: ((currVal: T) => T) | T): void;
142 reset(s: RecoilState<any>): void;
143 }
144 export interface CallbackInterface {
145 set: <T>(recoilVal: RecoilState<T>, valOrUpdater: ((currVal: T) => T) | T) => void;
146 reset: (recoilVal: RecoilState<any>) => void; // eslint-disable-line @typescript-eslint/no-explicit-any
147 refresh: (recoilValue: RecoilValue<any>) => void;
148 snapshot: Snapshot;
149 gotoSnapshot: (snapshot: Snapshot) => void;
150 transact_UNSTABLE: (cb: (i: TransactionInterface_UNSTABLE) => void) => void;
151 }
152
153 // selector.d.ts
154 export interface SelectorCallbackInterface extends CallbackInterface {
155 node: RecoilState<unknown>; // TODO This isn't properly typed
156 }
157 export type GetCallback = <Args extends ReadonlyArray<unknown>, Return>(
158 fn: (interface: SelectorCallbackInterface) => (...args: Args) => Return,
159 ) => (...args: Args) => Return;
160
161 export type SetRecoilState = <T>(
162 recoilVal: RecoilState<T>,
163 newVal: T | DefaultValue | ((prevValue: T) => T | DefaultValue),
164 ) => void;
165
166 export type ResetRecoilState = (recoilVal: RecoilState<any>) => void; // eslint-disable-line @typescript-eslint/no-explicit-any
167
168 // export type EqualityPolicy = 'reference' | 'value'; TODO: removing while we discuss long term API
169
170 export type EvictionPolicy = 'lru' | 'keep-all' | 'most-recent';
171
172 // TODO: removing while we discuss long term API
173 // export type CachePolicy =
174 // | {eviction: 'lru', maxSize: number, equality?: EqualityPolicy}
175 // | {eviction: 'none', equality?: EqualityPolicy}
176 // | {eviction?: undefined, equality: EqualityPolicy};
177
178 // TODO: removing while we discuss long term API
179 // export interface CachePolicyWithoutEviction {
180 // equality: EqualityPolicy;
181 // }
182
183 export type CachePolicyWithoutEquality = {eviction: 'lru', maxSize: number} | {eviction: 'keep-all'} | {eviction: 'most-recent'};
184
185 export interface ReadOnlySelectorOptions<T> {
186 key: string;
187 get: (opts: {
188 get: GetRecoilValue,
189 getCallback: GetCallback,
190 }) => Promise<T> | RecoilValue<T> | Loadable<T> | WrappedValue<T> | T;
191 dangerouslyAllowMutability?: boolean;
192 cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API
193 }
194
195 export interface ReadWriteSelectorOptions<T> extends ReadOnlySelectorOptions<T> {
196 set: (
197 opts: {
198 set: SetRecoilState;
199 get: GetRecoilValue;
200 reset: ResetRecoilState;
201 },
202 newValue: T | DefaultValue,
203 ) => void;
204 }
205
206 /**
207 * Creates a selector which represents derived state.
208 */
209 export function selector<T>(options: ReadWriteSelectorOptions<T>): RecoilState<T>;
210 export function selector<T>(options: ReadOnlySelectorOptions<T>): RecoilValueReadOnly<T>;
211 export namespace selector {
212 function value<T>(value: T): WrappedValue<T>;
213 }
214
215 // hooks.d.ts
216
217 /**
218 * Returns the value of an atom or selector (readonly or writeable) and
219 * subscribes the components to future updates of that state.
220 */
221 export function useRecoilValue<T>(recoilValue: RecoilValue<T>): T;
222
223 /**
224 * Returns a Loadable representing the status of the given Recoil state
225 * and subscribes the component to future updates of that state. Useful
226 * for working with async selectors.
227 */
228 export function useRecoilValueLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T>;
229
230 /**
231 * Returns a tuple where the first element is the value of the recoil state
232 * and the second is a setter to update that state. Subscribes component
233 * to updates of the given state.
234 */
235 export function useRecoilState<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>];
236
237 /**
238 * Returns a tuple where the first element is a Loadable and the second
239 * element is a setter function to update the given state. Subscribes
240 * component to updates of the given state.
241 */
242 export function useRecoilStateLoadable<T>(recoilState: RecoilState<T>): [Loadable<T>, SetterOrUpdater<T>];
243
244 /**
245 * Returns a setter function for updating Recoil state. Does not subscribe
246 * the component to the given state.
247 */
248
249 export function useSetRecoilState<T>(recoilState: RecoilState<T>): SetterOrUpdater<T>;
250
251 /**
252 * Returns a function that will reset the given state to its default value.
253 */
254 export function useResetRecoilState(recoilState: RecoilState<any>): Resetter; // eslint-disable-line @typescript-eslint/no-explicit-any
255
256 /**
257 * Returns current info about an atom
258 */
259 export function useGetRecoilValueInfo_UNSTABLE(): <T>(recoilValue: RecoilValue<T>) => RecoilStateInfo<T>;
260
261/**
262 * Experimental version of hooks for useTransition() support
263 */
264 export function useRecoilValue_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): T;
265 export function useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE<T>(recoilValue: RecoilValue<T>): Loadable<T>;
266 export function useRecoilState_TRANSITION_SUPPORT_UNSTABLE<T>(recoilState: RecoilState<T>): [T, SetterOrUpdater<T>];
267
268 /**
269 * Returns a function that will run the callback that was passed when
270 * calling this hook. Useful for accessing Recoil state in response to
271 * events.
272 */
273 export function useRecoilCallback<Args extends ReadonlyArray<unknown>, Return>(
274 fn: (interface: CallbackInterface) => (...args: Args) => Return,
275 deps?: ReadonlyArray<unknown>,
276 ): (...args: Args) => Return;
277
278 /**
279 * Returns a function that executes an atomic transaction for updating Recoil state.
280 */
281 export function useRecoilTransaction_UNSTABLE<Args extends ReadonlyArray<unknown>>(
282 fn: (interface: TransactionInterface_UNSTABLE) => (...args: Args) => void,
283 deps?: ReadonlyArray<unknown>,
284 ): (...args: Args) => void;
285
286 export function useRecoilTransactionObserver_UNSTABLE(
287 callback: (opts: {
288 snapshot: Snapshot,
289 previousSnapshot: Snapshot,
290 }) => void,
291 ): void;
292
293 /**
294 * Updates Recoil state to match the provided snapshot.
295 */
296 export function useGotoRecoilSnapshot(): (snapshot: Snapshot) => void;
297
298 /**
299 * Returns a snapshot of the current Recoil state and subscribes the component
300 * to re-render when any state is updated.
301 */
302 export function useRecoilSnapshot(): Snapshot;
303
304 // useRecoilRefresher.d.ts
305 /**
306 * Clears the cache for a selector causing it to be reevaluated.
307 */
308 export function useRecoilRefresher_UNSTABLE(recoilValue: RecoilValue<any>): () => void;
309
310 // useRecoilBridgeAcrossReactRoots.d.ts
311 export const RecoilBridge: React.FC<{children: React.ReactNode}>;
312 /**
313 * Returns a component that acts like a <RecoilRoot> but shares the same store
314 * as the current <RecoilRoot>.
315 */
316 export function useRecoilBridgeAcrossReactRoots_UNSTABLE(): typeof RecoilBridge;
317
318 // useRecoilStoreID
319 declare const StoreID_OPAQUE: unique symbol;
320 export interface StoreID {
321 readonly [StoreID_OPAQUE]: true;
322 }
323 /**
324 * Returns an ID for the currently active state store of the host <RecoilRoot>
325 */
326 export function useRecoilStoreID(): StoreID;
327
328 // loadable.d.ts
329 interface BaseLoadable<T> {
330 getValue: () => T;
331 toPromise: () => Promise<T>;
332 valueOrThrow: () => T;
333 errorOrThrow: () => any;
334 promiseOrThrow: () => Promise<T>;
335 is: (other: Loadable<any>) => boolean;
336 map: <S>(map: (from: T) => Loadable<S> | Promise<S> | S) => Loadable<S>;
337 }
338
339 interface ValueLoadable<T> extends BaseLoadable<T> {
340 state: 'hasValue';
341 contents: T;
342 valueMaybe: () => T;
343 errorMaybe: () => undefined;
344 promiseMaybe: () => undefined;
345 }
346
347 interface LoadingLoadable<T> extends BaseLoadable<T> {
348 state: 'loading';
349 contents: Promise<T>;
350 valueMaybe: () => undefined;
351 errorMaybe: () => undefined;
352 promiseMaybe: () => Promise<T>;
353 }
354
355 interface ErrorLoadable<T> extends BaseLoadable<T> {
356 state: 'hasError';
357 contents: any;
358 valueMaybe: () => undefined;
359 errorMaybe: () => any;
360 promiseMaybe: () => undefined;
361 }
362
363 export type Loadable<T> =
364 | ValueLoadable<T>
365 | LoadingLoadable<T>
366 | ErrorLoadable<T>;
367
368 // recoilValue.d.ts
369 declare class AbstractRecoilValue<T> {
370 __tag: [T];
371 __cTag: (t: T) => void; // for contravariance
372
373 key: NodeKey;
374 constructor(newKey: NodeKey);
375 }
376
377 declare class AbstractRecoilValueReadonly<T> {
378 __tag: [T];
379
380 key: NodeKey;
381 constructor(newKey: NodeKey);
382 }
383
384 export class RecoilState<T> extends AbstractRecoilValue<T> {}
385 export class RecoilValueReadOnly<T> extends AbstractRecoilValueReadonly<T> {}
386 export type RecoilValue<T> = RecoilValueReadOnly<T> | RecoilState<T>;
387
388 /**
389 * Returns true if the parameter is a Recoil atom or selector.
390 */
391 export function isRecoilValue(val: unknown): val is RecoilValue<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
392
393 /** Utilities */
394
395 // bigint not supported yet
396 type Primitive = undefined | null | boolean | number | symbol | string;
397 interface HasToJSON { toJSON(): SerializableParam; }
398
399 export type SerializableParam =
400 | Primitive
401 | HasToJSON
402 | ReadonlyArray<SerializableParam>
403 | ReadonlySet<SerializableParam>
404 | ReadonlyMap<SerializableParam, SerializableParam>
405 | Readonly<{[key: string]: SerializableParam}>;
406
407interface AtomFamilyOptionsWithoutDefault<T, P extends SerializableParam> {
408 key: NodeKey;
409 dangerouslyAllowMutability?: boolean;
410 effects?: | ReadonlyArray<AtomEffect<T>> | ((param: P) => ReadonlyArray<AtomEffect<T>>);
411 effects_UNSTABLE?: | ReadonlyArray<AtomEffect<T>> | ((param: P) => ReadonlyArray<AtomEffect<T>>);
412 // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API
413 }
414 interface AtomFamilyOptionsWithDefault<T, P extends SerializableParam> extends AtomFamilyOptionsWithoutDefault<T, P> {
415 default:
416 | RecoilValue<T>
417 | Promise<T>
418 | Loadable<T>
419 | WrappedValue<T>
420 | T
421 | ((param: P) => T | RecoilValue<T> | Promise<T> | Loadable<T> | WrappedValue<T>);
422 }
423 export type AtomFamilyOptions<T, P extends SerializableParam> =
424 | AtomFamilyOptionsWithDefault<T, P>
425 | AtomFamilyOptionsWithoutDefault<T, P>;
426
427 /**
428 * Returns a function which returns a memoized atom for each unique parameter value.
429 */
430 export function atomFamily<T, P extends SerializableParam>(
431 options: AtomFamilyOptions<T, P>,
432 ): (param: P) => RecoilState<T>;
433
434 export interface ReadOnlySelectorFamilyOptions<T, P extends SerializableParam> {
435 key: string;
436 get: (param: P) => (opts: {
437 get: GetRecoilValue,
438 getCallback: GetCallback,
439 }) => Promise<T> | RecoilValue<T> | Loadable<T> | WrappedValue<T> | T;
440 // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API
441 cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API
442 dangerouslyAllowMutability?: boolean;
443 }
444
445 export interface ReadWriteSelectorFamilyOptions<T, P extends SerializableParam> {
446 key: string;
447 get: (param: P) => (opts: {
448 get: GetRecoilValue,
449 getCallback: GetCallback,
450 }) => Promise<T> | Loadable<T> | WrappedValue<T> | RecoilValue<T> | T;
451 set: (
452 param: P,
453 ) => (
454 opts: { set: SetRecoilState; get: GetRecoilValue; reset: ResetRecoilState },
455 newValue: T | DefaultValue,
456 ) => void;
457 // cachePolicyForParams_UNSTABLE?: CachePolicyWithoutEviction; TODO: removing while we discuss long term API
458 cachePolicy_UNSTABLE?: CachePolicyWithoutEquality; // TODO: using the more restrictive CachePolicyWithoutEquality while we discuss long term API
459 dangerouslyAllowMutability?: boolean;
460 }
461
462/**
463 * Returns a function which returns a memoized atom for each unique parameter value.
464 */
465export function selectorFamily<T, P extends SerializableParam>(
466options: ReadWriteSelectorFamilyOptions<T, P>,
467): (param: P) => RecoilState<T>;
468
469/**
470 * Returns a function which returns a memoized atom for each unique parameter value.
471 */
472export function selectorFamily<T, P extends SerializableParam>(
473options: ReadOnlySelectorFamilyOptions<T, P>,
474): (param: P) => RecoilValueReadOnly<T>;
475
476/**
477 * Returns a selector that always has a constant value.
478 */
479export function constSelector<T extends SerializableParam>(constant: T): RecoilValueReadOnly<T>;
480
481/**
482 * Returns a selector which is always in the provided error state.
483 */
484export function errorSelector(message: string): RecoilValueReadOnly<never>;
485
486/**
487 * Casts a selector to be a read-only selector
488 */
489export function readOnlySelector<T>(atom: RecoilValue<T>): RecoilValueReadOnly<T>;
490
491/**
492 * Returns a selector that has the value of the provided atom or selector as a Loadable.
493 * This means you can use noWait() to avoid entering an error or suspense state in
494 * order to manually handle those cases.
495 */
496export function noWait<T>(state: RecoilValue<T>): RecoilValueReadOnly<Loadable<T>>;
497
498 /* eslint-disable @typescript-eslint/no-explicit-any */
499
500 export type UnwrapRecoilValue<T> = T extends RecoilValue<infer R> ? R : never;
501
502 export type UnwrapRecoilValues<T extends Array<RecoilValue<any>> | { [key: string]: RecoilValue<any> }> = {
503 [P in keyof T]: UnwrapRecoilValue<T[P]>;
504 };
505 export type UnwrapRecoilValueLoadables<T extends Array<RecoilValue<any>> | { [key: string]: RecoilValue<any> }> = {
506 [P in keyof T]: Loadable<UnwrapRecoilValue<T[P]>>;
507 };
508
509 export function waitForNone<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>(
510 param: RecoilValues,
511 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
512
513 export function waitForNone<RecoilValues extends { [key: string]: RecoilValue<any> }>(
514 param: RecoilValues,
515 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
516
517 export function waitForAny<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>(
518 param: RecoilValues,
519 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
520
521 export function waitForAny<RecoilValues extends { [key: string]: RecoilValue<any> }>(
522 param: RecoilValues,
523 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
524
525 export function waitForAll<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>(
526 param: RecoilValues,
527 ): RecoilValueReadOnly<UnwrapRecoilValues<RecoilValues>>;
528
529 export function waitForAll<RecoilValues extends { [key: string]: RecoilValue<any> }>(
530 param: RecoilValues,
531 ): RecoilValueReadOnly<UnwrapRecoilValues<RecoilValues>>;
532
533 export function waitForAllSettled<RecoilValues extends Array<RecoilValue<any>> | [RecoilValue<any>]>(
534 param: RecoilValues,
535 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
536
537 export function waitForAllSettled<RecoilValues extends { [key: string]: RecoilValue<any> }>(
538 param: RecoilValues,
539 ): RecoilValueReadOnly<UnwrapRecoilValueLoadables<RecoilValues>>;
540
541 export type UnwrapLoadable<T> = T extends Loadable<infer R> ? R : T extends Promise<infer P> ? P : T;
542 export type UnwrapLoadables<T extends any[] | { [key: string]: any }> = {
543 [P in keyof T]: UnwrapLoadable<T[P]>;
544 };
545
546 /* eslint-disable @typescript-eslint/no-unused-vars */
547 export namespace RecoilLoadable {
548 /**
549 * Factory to make a Loadable object. If a Promise is provided the Loadable will
550 * be in a 'loading' state until the Promise is either resolved or rejected.
551 */
552 function of<T>(x: T | Promise<T> | Loadable<T>): Loadable<T>;
553 /**
554 * Factory to make a Loadable object in an error state.
555 */
556 function error(x: any): ErrorLoadable<any>;
557 /**
558 * Factory to make a loading Loadable which never resolves.
559 */
560 function loading(): LoadingLoadable<any>;
561 /**
562 * Factory to make a Loadable which is resolved when all of the Loadables provided
563 * to it are resolved or any one has an error. The value is an array of the values
564 * of all of the provided Loadables. This is comparable to Promise.all() for Loadables.
565 * Similar to Promise.all(), inputs may be Loadables, Promises, or literal values.
566 */
567 function all<Inputs extends any[] | [Loadable<any>]>(inputs: Inputs): Loadable<UnwrapLoadables<Inputs>>;
568 function all<Inputs extends {[key: string]: any}>(inputs: Inputs): Loadable<UnwrapLoadables<Inputs>>;
569 /**
570 * Returns true if the provided parameter is a Loadable type.
571 */
572 function isLoadable(x: any): x is Loadable<any>;
573 }
574 /* eslint-enable @typescript-eslint/no-unused-vars */
575
576 /* eslint-enable @typescript-eslint/no-explicit-any */
577
578 /**
579 * Factory to produce a Recoil snapshot object with all atoms in the default state.
580 */
581 export function snapshot_UNSTABLE(initializeState?: (shapshot: MutableSnapshot) => void): Snapshot;