export type SharedValue = { value: Value; get(): Value; set(value: Value | ((value: Value) => Value)): void; addListener: (listenerID: number, listener: (value: Value) => void) => void; removeListener: (listenerID: number) => void; modify: ( modifier?: (value: T) => T, forceUpdate?: boolean ) => void; }; // Utility type that turns `T` into `T | SharedValue`. `P` is used to avoid splitting union types. export type SharedValueOrT = // We always want to get `T` in the resulting type. | T // If `T` is one of the types in `P`, we don't want to split the union, so we return SharedValue. | (Exclude extends P ? SharedValue> : // If `T` is not in `P`, we want to split the union and wrap each member with SharedValue, using Distributive Conditional Types (https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types). T extends any ? // Wrap each member of the union with SharedValue. SharedValue> : // If `T` is only one type, just return SharedValue. SharedValue>); // Utility type that decides whether to recurse for objects or apply SharedValue directly. export type WithSharedValue = T extends object ? WithSharedValueRecursive : Simplify>; // Apply SharedValue recursively. P is used to make sure that composed types won't be expanded. // For example, if we pass `HoverEffect` as P, then resulting type will have HoverEffect | SharedValue, // not HoverEffect, SharedValue, ... type WithSharedValueRecursive = { [K in keyof T]: Exclude extends P ? Simplify> : // Special case for boolean as passing `boolean` as P doesn't look ok. boolean extends T[K] ? boolean | SharedValue | Extract : // Special handling for tuples [number, number]. T[K] extends [number, number] ? [WithSharedValue, WithSharedValue] : // Default case: apply the MaybeWithSharedValue logic recursively or as a direct SharedValue wrap. WithSharedValue; }; // Simplifies types for end users. // For example, changes SharedValueOrT into number | SharedValue. type Simplify = T extends SharedValue ? never : // eslint-disable-next-line @typescript-eslint/no-explicit-any T extends SharedValue ? T : { // For a generic object, retain the original structure while forcing an object type [K in keyof T]: T[K]; } & NonNullable;