Skip to content

Commit

Permalink
Move types to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
luisherranz committed Jan 9, 2023
1 parent d312592 commit 1da837b
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 149 deletions.
158 changes: 9 additions & 149 deletions packages/deepsignal/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,151 +1,26 @@
import { computed, signal, Signal } from "@preact/signals-core";
import { computed, signal } from "@preact/signals-core";
import type {
DeepSignal,
DeepSignalObject,
RevertDeepSignalObject,
RevertDeepSignal,
WellKnownSymbols,
} from "./types";
export type { DeepSignal } from "./types";

const proxyToSignals = new WeakMap();
const objToProxy = new WeakMap();
const arrayToArrayOfSignals = new WeakMap();
const rg = /^\$\$?/;
let peeking = false;

type DeepSignalObject<T extends object> = {
[P in keyof T & string as `$${P}`]?: Signal<T[P]>;
} & {
[P in keyof T]: T[P] extends Array<unknown>
? DeepSignalArray<T[P]>
: T[P] extends object
? DeepSignalObject<T[P]>
: T[P];
};

// @ts-expect-error
interface MyArray<T> extends Array<T> {
map: <U>(
callbackfn: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => U,
thisArg?: any
) => U[];
forEach: (
callbackfn: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => void,
thisArg?: any
) => void;
concat(...items: ConcatArray<T>[]): DeepSignalArray<T[]>;
concat(...items: (T | ConcatArray<T>)[]): DeepSignalArray<T[]>;
reverse(): DeepSignalArray<T[]>;
shift(): DeepSignal<T> | undefined;
slice(start?: number, end?: number): DeepSignalArray<T[]>;
splice(start: number, deleteCount?: number): DeepSignalArray<T[]>;
splice(
start: number,
deleteCount: number,
...items: T[]
): DeepSignalArray<T[]>;
filter<S extends T>(
predicate: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => value is DeepSignal<S>,
thisArg?: any
): DeepSignalArray<S[]>;
filter(
predicate: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => unknown,
thisArg?: any
): DeepSignalArray<T[]>;
reduce(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => T
): DeepSignal<T>;
reduce(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => DeepSignal<T>,
initialValue: T
): DeepSignal<T>;
reduce<U>(
callbackfn: (
previousValue: U,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => U,
initialValue: U
): U;
reduceRight(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => T
): DeepSignal<T>;
reduceRight(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => DeepSignal<T>,
initialValue: T
): DeepSignal<T>;
reduceRight<U>(
callbackfn: (
previousValue: U,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => U,
initialValue: U
): U;
}
type ArrayType<T> = T extends Array<infer I> ? I : T;
type DeepSignalArray<T> = MyArray<ArrayType<T>> & {
[key: number]: DeepSignal<ArrayType<T>>;
$?: { [key: number]: Signal<ArrayType<T>> };
$length?: Signal<number>;
};

export type DeepSignal<T> = T extends Array<unknown>
? DeepSignalArray<T>
: T extends object
? DeepSignalObject<T>
: T;

export declare const useDeepSignal: <T extends object>(obj: T) => DeepSignal<T>;

export const deepSignal = <T extends object>(obj: T): DeepSignal<T> => {
if (!shouldProxy(obj)) throw new Error("This object can't be observed.");
if (!objToProxy.has(obj))
objToProxy.set(obj, new Proxy(obj, objectHandlers) as DeepSignal<T>);
return objToProxy.get(obj);
};

type FilterSignals<K> = K extends `$${infer P}` ? never : K;
type RevertDeepSignalObject<T> = Pick<T, FilterSignals<keyof T>>;
type RevertDeepSignalArray<T> = Omit<T, "$" | "$length">;

type RevertDeepSignal<T> = T extends Array<unknown>
? RevertDeepSignalArray<T>
: T extends object
? RevertDeepSignalObject<T>
: T;

export const peek = <
T extends DeepSignalObject<object>,
K extends keyof RevertDeepSignalObject<T>
Expand Down Expand Up @@ -228,21 +103,6 @@ const arrayHandlers = {
},
};

type WellKnownSymbols =
| "asyncIterator"
| "hasInstance"
| "isConcatSpreadable"
| "iterator"
| "match"
| "matchAll"
| "replace"
| "search"
| "species"
| "split"
| "toPrimitive"
| "toStringTag"
| "unscopables";

const wellKnownSymbols = new Set(
Object.getOwnPropertyNames(Symbol)
.map(key => Symbol[key as WellKnownSymbols])
Expand Down
159 changes: 159 additions & 0 deletions packages/deepsignal/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { Signal } from "@preact/signals-core";

export type DeepSignalObject<T extends object> = {
[P in keyof T & string as `$${P}`]?: Signal<T[P]>;
} & {
[P in keyof T]: T[P] extends Array<unknown>
? DeepSignalArray<T[P]>
: T[P] extends object
? DeepSignalObject<T[P]>
: T[P];
};

// @ts-expect-error
interface MyArray<T> extends Array<T> {
map: <U>(
callbackfn: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => U,
thisArg?: any
) => U[];
forEach: (
callbackfn: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => void,
thisArg?: any
) => void;
concat(...items: ConcatArray<T>[]): DeepSignalArray<T[]>;
concat(...items: (T | ConcatArray<T>)[]): DeepSignalArray<T[]>;
reverse(): DeepSignalArray<T[]>;
shift(): DeepSignal<T> | undefined;
slice(start?: number, end?: number): DeepSignalArray<T[]>;
splice(start: number, deleteCount?: number): DeepSignalArray<T[]>;
splice(
start: number,
deleteCount: number,
...items: T[]
): DeepSignalArray<T[]>;
filter<S extends T>(
predicate: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => value is DeepSignal<S>,
thisArg?: any
): DeepSignalArray<S[]>;
filter(
predicate: (
value: DeepSignal<T>,
index: number,
array: DeepSignalArray<T[]>
) => unknown,
thisArg?: any
): DeepSignalArray<T[]>;
reduce(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => T
): DeepSignal<T>;
reduce(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => DeepSignal<T>,
initialValue: T
): DeepSignal<T>;
reduce<U>(
callbackfn: (
previousValue: U,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => U,
initialValue: U
): U;
reduceRight(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => T
): DeepSignal<T>;
reduceRight(
callbackfn: (
previousValue: DeepSignal<T>,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => DeepSignal<T>,
initialValue: T
): DeepSignal<T>;
reduceRight<U>(
callbackfn: (
previousValue: U,
currentValue: DeepSignal<T>,
currentIndex: number,
array: DeepSignalArray<T[]>
) => U,
initialValue: U
): U;
}
type ArrayType<T> = T extends Array<infer I> ? I : T;
type DeepSignalArray<T> = MyArray<ArrayType<T>> & {
[key: number]: DeepSignal<ArrayType<T>>;
$?: { [key: number]: Signal<ArrayType<T>> };
$length?: Signal<number>;
};

export type DeepSignal<T> = T extends Array<unknown>
? DeepSignalArray<T>
: T extends object
? DeepSignalObject<T>
: T;

export declare const useDeepSignal: <T extends object>(obj: T) => DeepSignal<T>;

export declare const deepSignal: <T extends object>(obj: T) => DeepSignal<T>;

type FilterSignals<K> = K extends `$${infer P}` ? never : K;
export type RevertDeepSignalObject<T> = Pick<T, FilterSignals<keyof T>>;
type RevertDeepSignalArray<T> = Omit<T, "$" | "$length">;

export type RevertDeepSignal<T> = T extends Array<unknown>
? RevertDeepSignalArray<T>
: T extends object
? RevertDeepSignalObject<T>
: T;

export declare const peek: <
T extends DeepSignalObject<object>,
K extends keyof RevertDeepSignalObject<T>
>(
obj: T,
key: K
) => RevertDeepSignal<RevertDeepSignalObject<T>[K]>;

export type WellKnownSymbols =
| "asyncIterator"
| "hasInstance"
| "isConcatSpreadable"
| "iterator"
| "match"
| "matchAll"
| "replace"
| "search"
| "species"
| "split"
| "toPrimitive"
| "toStringTag"
| "unscopables";

0 comments on commit 1da837b

Please sign in to comment.