Skip to content

Commit

Permalink
refactor: make anys explicit
Browse files Browse the repository at this point in the history
  • Loading branch information
kalisjoshua committed Dec 27, 2024
1 parent 690c430 commit 66e1f8a
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 53 deletions.
30 changes: 20 additions & 10 deletions packages/core/src/composition/compose/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import type { ExplicitAny, UnaryFunction } from '@/types';
/*
* Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { UnaryFunction } from '@/types';

// https://stackoverflow.com/questions/49310886/typing-compose-function-in-typescript-flow-compose#answer-73082627

// If its a list of functions, last being Unary
type ComposeParams<Fns> = Fns extends readonly [
...ExplicitAny[],
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
...any[],
infer Last extends UnaryFunction,
]
? // Get Params of the last, which returns [...argTypes], so get the first one [0]
Expand All @@ -20,17 +34,13 @@ type Composable<Fn> =
Fn extends readonly [UnaryFunction]
? Fn
: // if its a list of Unary funcs (ignoring the first)
Fn extends readonly [
ExplicitAny,
...infer Rest extends readonly UnaryFunction[],
]
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Fn extends readonly [any, ...infer Rest extends readonly UnaryFunction[]]
? // Start building the list of func type by using the return type of the first in Rest
// as the arg of the next in line and recursively spread the rest (doing the same thing)
// The first is ignored but handled by the top level ComposeReturn
readonly [
(arg: ComposeReturn<Rest>) => ExplicitAny,
...Composable<Rest>,
]
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
readonly [(arg: ComposeReturn<Rest>) => any, ...Composable<Rest>]
: never;

/**
Expand Down
25 changes: 18 additions & 7 deletions packages/core/src/composition/curry/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
// https://github.com/type-challenges/type-challenges/issues/15988
/*
* Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import type { ExplicitAny } from '@/types';
import type { Callable } from '@/types';

// https://github.com/type-challenges/type-challenges/issues/15988
export type Curried<T extends unknown[], R> = <P extends Partial<T>>(
...args: P
) => ((...args: T) => ExplicitAny) extends (
...args: [...P, ...infer Args]
) => ExplicitAny
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
) => ((...args: T) => any) extends (...args: [...P, ...infer Args]) => any
? Args extends []
? R
: Curried<Args, R>
Expand All @@ -22,9 +32,10 @@ export type Curried<T extends unknown[], R> = <P extends Partial<T>>(
* curried(2)(3, 4);
* curried(2, 3, 4);
*/
export function autoCurry<T extends (...args: ExplicitAny[]) => ExplicitAny>(
export function autoCurry<T extends Callable>(
fn: T,
_args = [] as ExplicitAny[],
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
_args = [] as any[],
): Curried<Parameters<T>, ReturnType<T>> {
return (...__args) =>
((rest) => (rest.length >= fn.length ? fn(...rest) : autoCurry(fn, rest)))([
Expand Down
30 changes: 22 additions & 8 deletions packages/core/src/composition/pipe/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import type { ExplicitAny, UnaryFunction } from '@/types';
/*
* Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { UnaryFunction } from '@/types';

// If its a list of functions, last being Unary
type PipeParams<Fns> = Fns extends readonly [
infer First extends UnaryFunction,
...ExplicitAny[],
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
...any[],
]
? // Get Params of the first, which returns [...argTypes], so get the first one [0]
// so that we have the true type of the arg
Expand All @@ -14,7 +28,8 @@ type PipeParams<Fns> = Fns extends readonly [
// have to spread and infer last so that it gets the right type for the last one
// [-1] no bueno
type PipeReturn<Fns> = ReturnType<
Fns extends readonly [...ExplicitAny[], infer Last extends UnaryFunction]
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Fns extends readonly [...any[], infer Last extends UnaryFunction]
? Last
: never
>;
Expand All @@ -24,14 +39,13 @@ type Pipeable<Fn> =
Fn extends readonly [UnaryFunction]
? Fn
: // if its a list of Unary funcs (ignoring the last)
Fn extends readonly [
...infer Head extends readonly UnaryFunction[],
ExplicitAny,
]
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Fn extends readonly [...infer Head extends readonly UnaryFunction[], any]
? // Start building the list of func type by using the return type of the last in Head
// as the arg of the previous in line and recursively spread the rest (doing the same thing)
// The last is ignored but handled by the top level FlowReturn
readonly [...Pipeable<Head>, (arg: PipeReturn<Head>) => ExplicitAny]
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
readonly [...Pipeable<Head>, (arg: PipeReturn<Head>) => any]
: never;

/**
Expand Down
21 changes: 17 additions & 4 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
/*
* Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

export type Accumulator<T, R> = (acc: R, x: T) => R;

export type ArrayElementType<T> = T extends (infer E)[] ? E : T;

export type Comparator<T> = (x: T) => boolean;

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
export type ExplicitAny = any;
export type Callable = (...all: any) => any;

export type Comparator<T> = (x: T) => boolean;

export type MapFn<T, R> = (x: T, idx?: number) => R;

export type Predicate<T> = (x: T, idx?: number) => boolean;

export type UnaryFunction = (x: ExplicitAny) => ExplicitAny;
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
export type UnaryFunction = (x: any) => any;
19 changes: 6 additions & 13 deletions packages/core/src/utility/lookup/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { ExplicitAny } from '@/types';
import type { Callable } from '@/types';
import { identity } from '../../combinators/i';

type Cache = Record<string | number | symbol, unknown>;

/**
* Takes an object and an optional fallback function and returns a function that
* takes a string and returns the lookup value or the result default fallback.
Expand All @@ -17,15 +19,6 @@ import { identity } from '../../combinators/i';
* colorLookup(data.value);
*/
export const lookup =
<
A extends Record<string | number | symbol, unknown>,
B extends (...args: ExplicitAny[]) => ExplicitAny,
>(
obj: A,
def?: B,
) =>
<C extends keyof A>(prop: string | number | symbol): A[C] => {
const fn = def ?? identity;

return fn(obj[prop]);
};
<A extends Cache, B extends Callable>(obj: A, def?: B) =>
<C extends keyof A>(prop: string | number | symbol): A[C] =>
(def ?? identity)(obj[prop]);
20 changes: 9 additions & 11 deletions packages/core/src/utility/once/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import type { ExplicitAny } from '@/types';

// TS' `Function` type only models the object side of it, not whether it is callable.
type SomeFunction = (...args: ExplicitAny[]) => ExplicitAny;
import type { Callable } from '@/types';

/**
* Ensures that the given function is only called once.
*/
export const once = <T extends SomeFunction>(fn: T) => {
export const once = <T extends Callable>(fn: T) => {
let done = false;

// TODO: Better types, since it can return void?
// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
return (...args: Parameters<T>): ReturnType<T> | void =>
// biome-ignore lint/suspicious/noAssignInExpressions: Shhhh
// biome-ignore lint/style/noCommaOperator: Shhh
done ? void 0 : ((done = true), fn(args));
return (...args: Parameters<T>): ReturnType<T> | undefined => {
if (!done) {
done = true;

return fn(...args);
}
};
};

0 comments on commit 66e1f8a

Please sign in to comment.