Skip to content

Commit

Permalink
Add another Core version with partial and pipe as separate helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
gvergnaud committed Jul 16, 2023
1 parent 8dc9ff2 commit 0f510a0
Show file tree
Hide file tree
Showing 2 changed files with 418 additions and 38 deletions.
99 changes: 61 additions & 38 deletions src/internals/core/Core2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { _, unset } from "./Core";
import { ExcludePlaceholders, ExcludeUnset, MergeArgs } from "./impl/MergeArgs";
import * as NumberImpl from "../numbers/impl/numbers";
import * as StringImpl from "../strings/impl/strings";
import { Equal, Expect } from "../helpers";

/**
* Core
Expand All @@ -14,16 +15,6 @@ export interface Fn<input extends unknown[] = unknown[], output = unknown> {
return: unknown;
}

type Drop<
xs extends readonly unknown[],
n extends number,
dropped extends readonly unknown[] = []
> = n extends dropped["length"]
? xs
: xs extends readonly [infer first, ...infer tail]
? Drop<tail, n, [...dropped, first]>
: [];

type ExcludePlaceholdersFromInputTypes<
inputTypes extends unknown[],
partialArgs extends unknown[],
Expand Down Expand Up @@ -68,7 +59,7 @@ export type Apply<fn extends Fn, args extends unknown[]> = (fn & {
args: args;
})["return"];

type AnyAp = Ap<unknown, unknown>;
type AnyAp = Ap<any, any>;

export type $<
fn extends Fn,
Expand Down Expand Up @@ -107,6 +98,7 @@ type ExpectNumber<a extends number> = [a];
// arguments are typed internally:
interface TakeNumAndStr extends Fn<[number, string], boolean> {
works: ExpectNumber<Arg0<this>>; // ✅
// @ts-expect-error
fails: ExpectNumber<Arg1<this>>;
// ~~~~~~~~~~ ❌
return: true;
Expand All @@ -120,44 +112,61 @@ interface Div extends Fn<[number, number], number> {
* Full application
*/

type x = $<Div, 10, 2>; // 5
type t1 = $<Div, 10, 2>; // 5
// ^?
type y = $<Div, "10", 2>;
// ~~~ ❌
type z = $<Div, 11, "2">;
// ~~~ ❌
type test1 = Expect<Equal<t1, 5>>;

// @ts-expect-error
type err1 = $<Div, "10", 2>;
// ~~~ ❌

// @ts-expect-error
type err2 = $<Div, 11, "2">;
// ~~~ ❌

/**
* Partial application in order
*/

type Div1 = $<Div, 10>;
type Three = $<Div1, 2>;
type t2 = $<Div1, 2>;
// ^?
type test2 = Expect<Equal<t2, 5>>;
// ^?
type w = $<$<Div, 10>, "2">;
// ~~~ ❌

// @ts-expect-error
type t3 = $<$<Div, 10>, "2">;
// ~~~ ❌

/**
* Partial application different order
*/
type DivBy2 = $<Div, _, 2>;
// ^?
type q = $<DivBy2, 10>; // 5 ✅
type t4 = $<DivBy2, 10>; // 5 ✅
// ^?
type test4 = Expect<Equal<t4, 5>>;

type r = $<$<Div, _>, 10, 5>; // ✅
type t5 = $<$<Div, _>, 10, 5>; // ✅
// ^?
type test5 = Expect<Equal<t5, 2>>;

type TakeStr = $<TakeNumAndStr, 10>;
// ^? Ap<TakeNumAndStr, [10]>
type e = $<TakeStr, 10>;
// ~~ ❌

// @ts-expect-error
type t8 = $<TakeStr, 10>;
// ~~ ❌

type TakeNum = $<TakeNumAndStr, _, "10">;
// ^?Ap<TakeNumAndStr, [_, "10"]>
type s = $<TakeNum, 10>; // ✅
type d = $<TakeNum, "10">;
// ~~~~ ❌

type t7 = $<TakeNum, 10>; // ✅
type test7 = Expect<Equal<t7, true>>;

// @ts-expect-error
type t8 = $<TakeNum, "10">;
// ~~~~ ❌

/**
* Higher order
Expand All @@ -169,8 +178,9 @@ interface Map<A = unknown, B = unknown> extends Fn<[Fn<[A], B>, A[]], B[]> {
: never;
}

type z2 = $<Map<number, number>, $<Div, _, 2>, [2, 4, 6, 8, 10]>;
type t9 = $<Map<number, number>, $<Div, _, 2>, [2, 4, 6, 8, 10]>;
// ^? [1, 2, 3, 4, 5]
type test9 = Expect<Equal<t9, [1, 2, 3, 4, 5]>>;

interface Add extends Fn<[number, number], number> {
return: NumberImpl.Add<Arg0<this>, Arg1<this>>;
Expand All @@ -194,14 +204,21 @@ interface Reduce<A = unknown, B = unknown>
: never;
}

type reduced1 = $<Reduce<number, number>, Add, 0, [2, 4, 6, 8, 10]>;
type t11 = $<Reduce<number, number>, Add, 0, [2, 4, 6, 8, 10]>;
// ^? 30
type reduced2 = $<Reduce<number, number>, Mul, 1, [2, 4, 6, 8, 10]>;
type test11 = Expect<Equal<t11, 30>>;

type t12 = $<Reduce<number, number>, Mul, 1, [2, 4, 6, 8, 10]>;
// ^? 3840
type reduced3 = $<Reduce<number, number>, Mul, 1, ["2", "4", "6", "8", "10"]>;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~ ❌
type reducedOops = $<Reduce, Mul, 1, "oops">;
// ~~~~~~ ❌
type test12 = Expect<Equal<t12, 3840>>;

// @ts-expect-error
type t13 = $<Reduce<number, number>, Mul, 1, ["2", "4", "6", "8", "10"]>;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~ ❌

// @ts-expect-error
type t14 = $<Reduce, Mul, 1, "oops">;
// ~~~~~~ ❌

interface NumToStringReducer extends Fn<[string, number], string> {
return: `${Arg0<this>}${Arg1<this>}`;
Expand All @@ -212,12 +229,14 @@ interface StringToNumReducer extends Fn<[number, string], number> {
}

// prettier-ignore
type reduced4 = $<Reduce<string, number>, StringToNumReducer, 1, ["a", "aa", "aaa", "aaaa", "aaaaa"]>;
type t15 = $<Reduce<string, number>, StringToNumReducer, 1, ["a", "aa", "aaa", "aaaa", "aaaaa"]>;
// ^? 16
type test15 = Expect<Equal<t15, 16>>;

// @ts-expect-error
// prettier-ignore
type reduced5 = $<Reduce<string, number>, NumToStringReducer, 1, ["a", "aa", "aaa", "aaaa", "aaaaa"]>;
// ~~~~~~~~~~~~~~~~~~ ❌
type t16 = $<Reduce<string, number>, NumToStringReducer, 1, ["a", "aa", "aaa", "aaaa", "aaaaa"]>;
// ~~~~~~~~~~~~~~~~~~ ❌

interface ToString extends Fn<[number], string> {
return: `${Arg0<this>}`;
Expand All @@ -237,15 +256,19 @@ interface ToArray extends Fn<[unknown], [unknown]> {

type Times10<T extends number> = $<Prepend, "1", $<ToString, T>>;

type test1 = Times10<10>;
type t17 = Times10<10>;
// ^? 110
type test17 = Expect<Equal<t17, "110">>;

// @ts-expect-error
type WrongComposition1<T extends string> = $<Prepend, "1", $<ToNumber, T>>;
// ~~~~~~~~~~~~~~ ❌
// @ts-expect-error
type WrongComposition2<T extends number> = $<Add, 1, $<ToString, T>>;
// ~~~~~~~~~~~~~~ ❌

type Test<T extends string> = $<Prepend, "1", T>;

type test2 = Test<"10">;
type t18 = Test<"10">;
// ^? 110
type test18 = Expect<Equal<t18, "110">>;
Loading

0 comments on commit 0f510a0

Please sign in to comment.