Skip to content

Commit

Permalink
refactor: simplify/improve effect types
Browse files Browse the repository at this point in the history
I will refer to all of `create(Computed|RenderEffect|Effect|Memo)` as `createEffect` for brevity.
- Simplified `createEffect` such that it no longer needs the use of rest params.
- Added test cases for effect functions failing partial generic inference (not supported by typescript)
  • Loading branch information
otonashixav committed Apr 2, 2022
1 parent 9cd3f26 commit 8435b68
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 22 deletions.
42 changes: 21 additions & 21 deletions packages/solid/src/reactive/signal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,16 @@ export type EffectFunction<Prev, Next extends Prev = Prev> = (v: Prev) => Next;
*
* @description https://www.solidjs.com/docs/latest/api#createcomputed
*/
export function createComputed<Next>(
fn: EffectFunction<undefined | NoInfer<Next>, Next>,
value?: undefined,
options?: EffectOptions
): void;
export function createComputed<Next, Init = Next>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
options?: EffectOptions
): void;
export function createComputed<Next, Init = undefined>(
..._: undefined extends Init
? [fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions]
: [fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions]
): void;
export function createComputed<Next, Init>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
Expand All @@ -248,16 +248,16 @@ export function createComputed<Next, Init>(
*
* @description https://www.solidjs.com/docs/latest/api#createrendereffect
*/
export function createRenderEffect<Next>(
fn: EffectFunction<undefined | NoInfer<Next>, Next>,
value?: undefined,
options?: EffectOptions
): void;
export function createRenderEffect<Next, Init = Next>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
options?: EffectOptions
): void;
export function createRenderEffect<Next, Init = undefined>(
..._: undefined extends Init
? [fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions]
: [fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions]
): void;
export function createRenderEffect<Next, Init>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
Expand All @@ -283,17 +283,17 @@ export function createRenderEffect<Next, Init>(
*
* @description https://www.solidjs.com/docs/latest/api#createeffect
*/
export function createEffect<Next>(
fn: EffectFunction<undefined | NoInfer<Next>, Next>,
value?: undefined,
options?: EffectOptions
): void;
export function createEffect<Next, Init = Next>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
options?: EffectOptions
): void;
export function createEffect<Next, Init = undefined>(
..._: undefined extends Init
? [fn: EffectFunction<Init | Next, Next>, value?: Init, options?: EffectOptions]
: [fn: EffectFunction<Init | Next, Next>, value: Init, options?: EffectOptions]
): void;
export function createEffect<Next, Init = Next>(
export function createEffect<Next, Init>(
fn: EffectFunction<Init | Next, Next>,
value: Init,
options?: EffectOptions
Expand Down Expand Up @@ -366,16 +366,16 @@ export interface MemoOptions<T> extends EffectOptions {
// The extra _Next generic parameter separates inference of the effect input
// parameter type from inference of the effect return type, so that the effect
// return type is always used as the memo Accessor's return type.
export function createMemo<Next extends _Next, _Next = Next>(
fn: EffectFunction<undefined | NoInfer<_Next>, Next>,
value?: undefined,
options?: MemoOptions<Next>
): Accessor<Next>;
export function createMemo<Next extends _Next, Init = Next, _Next = Next>(
fn: EffectFunction<Init | _Next, Next>,
value: Init,
options?: MemoOptions<Next>
): Accessor<Next>;
export function createMemo<Next extends _Next, Init = undefined, _Next = Next>(
..._: undefined extends Init
? [fn: EffectFunction<Init | _Next, Next>, value?: Init, options?: MemoOptions<Next>]
: [fn: EffectFunction<Init | _Next, Next>, value: Init, options?: MemoOptions<Next>]
): Accessor<Next>;
export function createMemo<Next extends _Next, Init, _Next>(
fn: EffectFunction<Init | _Next, Next>,
value: Init,
Expand Down
13 changes: 12 additions & 1 deletion packages/solid/test/signals.type-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ const m2: Accessor<number | undefined> = createMemo(() => 123);
const m3: //
Accessor<undefined> = createMemo(() => {});
const m4: Accessor<void> = createMemo(() => {});
// @ts-expect-error memo type is determined by the return type, not parameters
const m5: Accessor<number | undefined> = createMemo(
// @ts-expect-error void can't be assigned to anything!
(v?: number) => {}
Expand All @@ -602,6 +603,7 @@ const m11: Accessor<number | undefined> = createMemo<number | undefined>(
v => {},
123
);
// @ts-expect-error memo type is determined by the return type, not parameters
const m12: Accessor<number | undefined> = createMemo(
// @ts-expect-error void can't be assigned to anything!
(v?: number) => {},
Expand All @@ -625,7 +627,6 @@ const m18: Accessor<number> =
const m19: Accessor<number> =
// @ts-expect-error undefined initial value is not assignable to the number parameter
createMemo((v: number | string): number => 123);
// @ts-expect-error because the number return cannot be assigned to the boolean|string parameter
const m20: Accessor<number> =
// @ts-expect-error because the number return cannot be assigned to the boolean|string parameter
createMemo((v: boolean | string): number => 123);
Expand Down Expand Up @@ -919,3 +920,13 @@ createRenderEffect<number | boolean>(
// @ts-expect-error string return is not assignable to number|boolean
"foo"
);

// FIXME cases failing due to partial generic inference not being implemented
// @ts-expect-error second generic is not inferred and remains as number
const a7: Accessor<number> = createMemo<number>((v: number | string) => 123, "asd");
// @ts-expect-error second generic is not inferred and remains as number
createEffect<number>((v: number | string) => 123, "asd");
// @ts-expect-error second generic is not inferred and remains as number
createComputed<number>((v: number | string) => 123, "asd");
// @ts-expect-error second generic is not inferred and remains as number
createRenderEffect<number>((v: number | string) => 123, "asd");

0 comments on commit 8435b68

Please sign in to comment.