diff --git a/src/internals/core/Core2.ts b/src/internals/core/Core2.ts index d0e1800..3493ff6 100644 --- a/src/internals/core/Core2.ts +++ b/src/internals/core/Core2.ts @@ -2,7 +2,6 @@ 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 { Iterator } from "../helpers"; /** * Core @@ -25,6 +24,21 @@ type Drop< ? Drop : []; +type ExcludePlaceholdersFromInputTypes< + inputTypes extends any[], + partialArgs extends any[], + result extends any[] = [] +> = [inputTypes, partialArgs] extends [ + [infer fInput, ...infer rInput], + [infer fPartial, ...infer rPartial] +] + ? ExcludePlaceholdersFromInputTypes< + rInput, + rPartial, + fPartial extends _ ? [...result, fInput] : result + > + : [...result, ...inputTypes]; + interface Ap extends Fn { name: "Ap"; @@ -34,15 +48,18 @@ interface Ap extends Fn { expectedArgsCount: fn["inputTypes"]["length"]; providedArgsCount: ExcludePlaceholders["length"]; - inputTypes: Drop< - fn["inputTypes"], - ExcludePlaceholders["length"] - >; + inputTypes: ExcludePlaceholdersFromInputTypes; + + outputType: fn["outputType"]; - return: NumberImpl.Compare< + isFullyApplied: NumberImpl.Compare< this["providedArgsCount"], this["expectedArgsCount"] > extends 1 | 0 + ? true + : false; + + return: this["isFullyApplied"] extends true ? Apply> : Ap; } @@ -51,24 +68,40 @@ export type Apply = (fn & { args: args; })["return"]; +type AnyAp = Ap; + export type $< fn extends Fn, - arg0 extends fn["inputTypes"][0] | _ = unset, - arg1 extends fn["inputTypes"][1] | _ = unset, - arg2 extends fn["inputTypes"][2] | _ = unset, - arg3 extends fn["inputTypes"][3] | _ = unset -> = Extract< - ((fn extends { name: "Ap" } ? fn : Ap) & { - args: ExcludeUnset<[arg0, arg1, arg2, arg3]>; - })["return"], - fn["outputType"] + arg0 extends fn["inputTypes"][0] | AnyAp | _ = unset, + arg1 extends fn["inputTypes"][1] | AnyAp | _ = unset, + arg2 extends fn["inputTypes"][2] | AnyAp | _ = unset, + arg3 extends fn["inputTypes"][3] | AnyAp | _ = unset, + ap extends AnyAp = fn extends { name: "Ap" } ? fn : Ap +> = (ap & { + args: ExcludeUnset<[arg0, arg1, arg2, arg3]>; +})["return"]; + +type Args = fn["args"]; +type Arg0 = Extract< + Extract[0], + fn["inputTypes"][0] +>; +type Arg1 = Extract< + Extract[1], + fn["inputTypes"][1] +>; +type Arg2 = Extract< + Extract[2], + fn["inputTypes"][2] +>; +type Arg3 = Extract< + Extract[3], + fn["inputTypes"][3] >; -type Args = Extract; -type Arg0 = Extract[0]; -type Arg1 = Extract[1]; -type Arg2 = Extract[2]; -type Arg3 = Extract[3]; +/** + * Playground 👇 + */ type ExpectNumber = [a]; // arguments are typed internally: @@ -111,6 +144,7 @@ type DivBy2 = $; // ^? type q = $; // 5 ✅ // ^? + type r = $<$, 10, 5>; // ✅ // ^? @@ -121,20 +155,21 @@ type e = $; type TakeNum = $; // ^?Ap -type s = $; -// ~~ FIXME +type s = $; // ✅ +type d = $; +// ~~~~ ❌ /** * Higher order */ -interface Map extends Fn<[Fn, any[]]> { +interface Map extends Fn<[Fn<[A], B>, A[]], B[]> { return: Args extends [infer fn extends Fn, infer tuple] ? { [key in keyof tuple]: $ } : never; } -type z2 = $, [2, 4, 6, 8, 10]>; +type z2 = $, $, [2, 4, 6, 8, 10]>; // ^? [1, 2, 3, 4, 5] interface Add extends Fn<[number, number], number> { @@ -192,20 +227,24 @@ interface ToNumber extends Fn<[string], number> { } interface Prepend extends Fn<[string, string], string> { - return: this["args"] extends [ - infer first extends string, - infer str extends string - ] - ? `${first}${str}` - : never; + return: `${Arg0}${Arg1}`; +} + +interface ToArray extends Fn<[any], [any]> { + return: [Arg0]; } -type Times10 = $>>; +type Times10 = $>; + +type test1 = Times10<10>; +// ^? 110 type WrongComposition1 = $>; // ~~~~~~~~~~~~~~ ❌ type WrongComposition2 = $>; // ~~~~~~~~~~~~~~ ❌ -type test1 = Times10<10>; +type Test = $; + +type test2 = Test<"10">; // ^? 110