chore: DRY the types
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ export default defineConfig([
|
|||||||
"@typescript-eslint/no-unused-vars": [
|
"@typescript-eslint/no-unused-vars": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
varsIgnorePattern: "^_",
|
varsIgnorePattern: "^_[^_]",
|
||||||
reportUsedIgnorePattern: true,
|
reportUsedIgnorePattern: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ export interface Identity extends HKT {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
export const never = undefined as never;
|
export const never = undefined as never;
|
||||||
|
|
||||||
export type MaxDepth = 20;
|
|
||||||
|
|
||||||
export class AssertionError extends Error {
|
export class AssertionError extends Error {
|
||||||
public constructor(msg?: string) {
|
public constructor(msg?: string) {
|
||||||
super(msg);
|
super(msg);
|
||||||
|
|||||||
+2
-85
@@ -2,6 +2,7 @@ import { makeFluent } from "../base";
|
|||||||
import type { HKT } from "../base/hkt";
|
import type { HKT } from "../base/hkt";
|
||||||
import { Mixin, type Input, type Return } from "../base/mixin";
|
import { Mixin, type Input, type Return } from "../base/mixin";
|
||||||
import { assert, assertType, type HidePrototype } from "../internal";
|
import { assert, assertType, type HidePrototype } from "../internal";
|
||||||
|
import type { MaxDepth, At } from "../utility";
|
||||||
|
|
||||||
type IterArgs<T extends readonly unknown[] = unknown[]> = [
|
type IterArgs<T extends readonly unknown[] = unknown[]> = [
|
||||||
element: T[number],
|
element: T[number],
|
||||||
@@ -9,11 +10,7 @@ type IterArgs<T extends readonly unknown[] = unknown[]> = [
|
|||||||
array: Readonly<T>,
|
array: Readonly<T>,
|
||||||
];
|
];
|
||||||
|
|
||||||
type MaxDepth = 20;
|
type Unordered<T extends readonly unknown[]> = T[number][];
|
||||||
|
|
||||||
type Unordered<T extends readonly unknown[]> = T extends unknown[]
|
|
||||||
? T[number][]
|
|
||||||
: readonly T[number][];
|
|
||||||
|
|
||||||
type Map<
|
type Map<
|
||||||
T extends readonly unknown[],
|
T extends readonly unknown[],
|
||||||
@@ -38,54 +35,6 @@ type Reverse<
|
|||||||
? TOut
|
? TOut
|
||||||
: T[number][];
|
: T[number][];
|
||||||
|
|
||||||
namespace At {
|
|
||||||
export type Dec<N extends number> = [
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
5,
|
|
||||||
6,
|
|
||||||
7,
|
|
||||||
8,
|
|
||||||
9,
|
|
||||||
10,
|
|
||||||
11,
|
|
||||||
12,
|
|
||||||
13,
|
|
||||||
14,
|
|
||||||
15,
|
|
||||||
16,
|
|
||||||
17,
|
|
||||||
18,
|
|
||||||
19,
|
|
||||||
20,
|
|
||||||
21,
|
|
||||||
][N];
|
|
||||||
|
|
||||||
export type Select<
|
|
||||||
T extends readonly unknown[],
|
|
||||||
Skip extends number,
|
|
||||||
> = Skip extends 0
|
|
||||||
? T extends readonly [...unknown[], infer T]
|
|
||||||
? T
|
|
||||||
: undefined
|
|
||||||
: T extends readonly [...infer TRest, unknown]
|
|
||||||
? Select<TRest, Dec<Skip>>
|
|
||||||
: undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
type At<
|
|
||||||
T extends readonly unknown[],
|
|
||||||
K extends keyof T & number,
|
|
||||||
> = number extends T["length"]
|
|
||||||
? T[K] | undefined
|
|
||||||
: `${K}` extends `-${infer N extends number}`
|
|
||||||
? At.Select<T, At.Dec<N>>
|
|
||||||
: T[K];
|
|
||||||
|
|
||||||
type Repeat<
|
type Repeat<
|
||||||
T extends readonly unknown[],
|
T extends readonly unknown[],
|
||||||
N extends number,
|
N extends number,
|
||||||
@@ -97,38 +46,6 @@ type Repeat<
|
|||||||
? T[number][]
|
? T[number][]
|
||||||
: Repeat<T, N, [...Acc, null], [...TOut, ...T]>;
|
: Repeat<T, N, [...Acc, null], [...TOut, ...T]>;
|
||||||
|
|
||||||
namespace Flat {
|
|
||||||
type Inc<
|
|
||||||
N extends number,
|
|
||||||
Acc extends unknown[] = [],
|
|
||||||
> = Acc["length"] extends N
|
|
||||||
? [...Acc, null]["length"]
|
|
||||||
: Inc<N, [...Acc, null]>;
|
|
||||||
|
|
||||||
export type Leaves<
|
|
||||||
T,
|
|
||||||
Depth extends number = 0,
|
|
||||||
> = Depth extends MaxDepth
|
|
||||||
? T
|
|
||||||
: T extends readonly unknown[]
|
|
||||||
? Leaves<T[number], Inc<Depth>>
|
|
||||||
: T;
|
|
||||||
|
|
||||||
export type Rebuild<
|
|
||||||
T extends readonly unknown[],
|
|
||||||
Depth extends number = 0,
|
|
||||||
> = Depth extends MaxDepth
|
|
||||||
? T
|
|
||||||
: T extends readonly [infer H, ...infer R]
|
|
||||||
? H extends readonly unknown[]
|
|
||||||
? [...Rebuild<H, Inc<Depth>>, ...Rebuild<R, Depth>]
|
|
||||||
: [H, ...Rebuild<R, Depth>]
|
|
||||||
: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Flat<T extends readonly unknown[]> =
|
|
||||||
number extends T["length"] ? Flat.Leaves<T>[] : Flat.Rebuild<T>;
|
|
||||||
|
|
||||||
function isArray(v: unknown): v is readonly unknown[] {
|
function isArray(v: unknown): v is readonly unknown[] {
|
||||||
return typeof v === "object" && globalThis.Array.isArray(v);
|
return typeof v === "object" && globalThis.Array.isArray(v);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-13
@@ -6,21 +6,10 @@ import {
|
|||||||
type Props,
|
type Props,
|
||||||
type Return,
|
type Return,
|
||||||
} from "../base/mixin";
|
} from "../base/mixin";
|
||||||
import { assertType, type MaxDepth } from "../internal";
|
import { assertType } from "../internal";
|
||||||
|
import type { Inc } from "../utility";
|
||||||
import { applySwizzle, type Swizzle } from "./math/swizzle";
|
import { applySwizzle, type Swizzle } from "./math/swizzle";
|
||||||
|
|
||||||
type Vec<
|
|
||||||
T,
|
|
||||||
N extends number,
|
|
||||||
TOut extends T[] = [],
|
|
||||||
> = TOut["length"] extends N
|
|
||||||
? TOut
|
|
||||||
: TOut["length"] extends MaxDepth
|
|
||||||
? T[]
|
|
||||||
: Vec<T, N, [...TOut, T]>;
|
|
||||||
|
|
||||||
type Inc<N extends number> = [...Vec<null, N>, null]["length"];
|
|
||||||
|
|
||||||
type Sign<T extends number> = T extends 0
|
type Sign<T extends number> = T extends 0
|
||||||
? 0
|
? 0
|
||||||
: `${T}` extends `-${number}`
|
: `${T}` extends `-${number}`
|
||||||
|
|||||||
@@ -1,26 +1,13 @@
|
|||||||
import { makeFluent } from "../../base";
|
import { makeFluent } from "../../base";
|
||||||
import type { Props, Return } from "../../base/mixin";
|
import type { Props, Return } from "../../base/mixin";
|
||||||
import { type MaxDepth } from "../../internal";
|
|
||||||
import { Math } from "../math";
|
import { Math } from "../math";
|
||||||
|
import type { Vec, Dec, Inc as __Inc } from "../../utility";
|
||||||
|
|
||||||
type Axis = typeof axis;
|
type Axis = typeof axis;
|
||||||
type Vec<
|
|
||||||
T,
|
|
||||||
N extends number,
|
|
||||||
TOut extends T[] = [],
|
|
||||||
> = TOut["length"] extends N
|
|
||||||
? TOut
|
|
||||||
: TOut["length"] extends MaxDepth
|
|
||||||
? T[]
|
|
||||||
: Vec<T, N, [...TOut, T]>;
|
|
||||||
|
|
||||||
type Inc<N extends number | undefined> = N extends number
|
type Inc<N extends number | undefined> = N extends number
|
||||||
? [...Vec<null, N>, null]["length"]
|
? __Inc<N>
|
||||||
: 0;
|
: 0;
|
||||||
type Dec<N extends number> =
|
|
||||||
Vec<null, N> extends [...infer Rest extends null[], null]
|
|
||||||
? Rest["length"]
|
|
||||||
: -1;
|
|
||||||
|
|
||||||
type Next<
|
type Next<
|
||||||
N extends number,
|
N extends number,
|
||||||
@@ -52,13 +39,8 @@ type Key<
|
|||||||
type IsAscending<
|
type IsAscending<
|
||||||
State extends (number | undefined)[],
|
State extends (number | undefined)[],
|
||||||
Prev extends number | undefined = undefined,
|
Prev extends number | undefined = undefined,
|
||||||
> = State extends readonly [
|
> = State extends readonly [Inc<Prev>, ...infer Rest extends number[]]
|
||||||
infer Current extends number,
|
|
||||||
...infer Rest extends number[],
|
|
||||||
]
|
|
||||||
? Current extends Inc<Prev>
|
|
||||||
? IsAscending<Rest, Inc<Prev>>
|
? IsAscending<Rest, Inc<Prev>>
|
||||||
: false
|
|
||||||
: State extends readonly []
|
: State extends readonly []
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
|
|||||||
+252
@@ -0,0 +1,252 @@
|
|||||||
|
export type MaxDepth = 50;
|
||||||
|
|
||||||
|
export type Pretty<T> = { [K in keyof T]: T[K] };
|
||||||
|
export type Constrain<T, U> = T extends U ? T : never;
|
||||||
|
|
||||||
|
namespace Vec {
|
||||||
|
// prettier-ignore
|
||||||
|
type Lookup<T, N extends number> = N extends 0
|
||||||
|
? []
|
||||||
|
: N extends 1
|
||||||
|
? [T]
|
||||||
|
: N extends 2
|
||||||
|
? [T, T]
|
||||||
|
: N extends 3
|
||||||
|
? [T, T, T]
|
||||||
|
: N extends 4
|
||||||
|
? [T, T, T, T]
|
||||||
|
: N extends 5
|
||||||
|
? [T, T, T, T, T]
|
||||||
|
: N extends 6
|
||||||
|
? [T, T, T, T, T, T]
|
||||||
|
: N extends 7
|
||||||
|
? [T, T, T, T, T, T, T]
|
||||||
|
: N extends 8
|
||||||
|
? [T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 9
|
||||||
|
? [T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 10
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 11
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 12
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 13
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 14
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 15
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 16
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 17
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 18
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 19
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: N extends 20
|
||||||
|
? [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]
|
||||||
|
: [T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T];
|
||||||
|
|
||||||
|
export type Recursive<
|
||||||
|
T,
|
||||||
|
N extends number,
|
||||||
|
TOut extends T[] = Lookup<T, N>,
|
||||||
|
TAcc extends never[] = [],
|
||||||
|
> = TOut["length"] extends N
|
||||||
|
? TOut
|
||||||
|
: TAcc["length"] extends MaxDepth
|
||||||
|
? T[]
|
||||||
|
: Recursive<T, N, [...TOut, T], [...TAcc, never]>;
|
||||||
|
}
|
||||||
|
export type Vec<
|
||||||
|
T,
|
||||||
|
N extends number,
|
||||||
|
Readonly extends boolean = false,
|
||||||
|
> = number extends N
|
||||||
|
? Readonly extends true
|
||||||
|
? readonly T[]
|
||||||
|
: T[]
|
||||||
|
: `${N}` extends `${infer U extends number}${`.${number}` | ""}`
|
||||||
|
? `${N}` extends `-${number}`
|
||||||
|
? T[]
|
||||||
|
: Vec.Recursive<T, U> extends infer V
|
||||||
|
? Readonly extends true
|
||||||
|
? { readonly [K in keyof V]: V[K] }
|
||||||
|
: V
|
||||||
|
: never
|
||||||
|
: T[];
|
||||||
|
|
||||||
|
export type Inc<N extends number> = Constrain<
|
||||||
|
number extends N ? number : [...Vec<never, N>, never]["length"],
|
||||||
|
number
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type Dec<N extends number> = N extends 0
|
||||||
|
? -1
|
||||||
|
: `${N}` extends `-${infer U extends number}`
|
||||||
|
? `-${Inc<U>}` extends `${infer O extends number}`
|
||||||
|
? O
|
||||||
|
: never
|
||||||
|
: `${N}` extends `${number}`
|
||||||
|
? Vec<never, N> extends [never, ...infer Rest]
|
||||||
|
? Rest["length"]
|
||||||
|
: number
|
||||||
|
: number;
|
||||||
|
|
||||||
|
namespace At {
|
||||||
|
export type FindBack<
|
||||||
|
T extends readonly unknown[],
|
||||||
|
N extends number,
|
||||||
|
TAcc extends never[] = [],
|
||||||
|
> = T extends readonly [...infer Rest, infer Last]
|
||||||
|
? TAcc["length"] extends N
|
||||||
|
? Last
|
||||||
|
: TAcc["length"] extends MaxDepth
|
||||||
|
? Rest[number]
|
||||||
|
: FindBack<Rest, N, [...TAcc, never]>
|
||||||
|
: T extends readonly []
|
||||||
|
? undefined
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type Sequence<
|
||||||
|
T extends readonly unknown[],
|
||||||
|
N extends readonly number[],
|
||||||
|
Fallback extends T[number][],
|
||||||
|
TOut extends T[number][] = [],
|
||||||
|
> = TOut["length"] extends MaxDepth
|
||||||
|
? Fallback
|
||||||
|
: N extends readonly [
|
||||||
|
infer Current extends number,
|
||||||
|
...infer Rest extends number[],
|
||||||
|
]
|
||||||
|
? Sequence<T, Rest, Fallback, [...TOut, At<T, Current>]>
|
||||||
|
: N extends readonly []
|
||||||
|
? TOut
|
||||||
|
: never;
|
||||||
|
}
|
||||||
|
export type At<
|
||||||
|
T extends readonly unknown[],
|
||||||
|
N extends number | readonly number[],
|
||||||
|
> = N extends readonly number[]
|
||||||
|
? number extends N["length"]
|
||||||
|
? (T[number] | undefined)[]
|
||||||
|
: At.Sequence<T, N, Vec<T[number], N["length"]>>
|
||||||
|
: N extends number
|
||||||
|
? N extends `${number}.${number}`
|
||||||
|
? undefined
|
||||||
|
: number extends T["length"]
|
||||||
|
? T[number] | undefined
|
||||||
|
: `${N}` extends `-${infer U extends number}`
|
||||||
|
? At.FindBack<T, Dec<U>>
|
||||||
|
: T[N]
|
||||||
|
: never;
|
||||||
|
|
||||||
|
namespace Flat {
|
||||||
|
export type Simple<
|
||||||
|
T,
|
||||||
|
Depth extends number = 0,
|
||||||
|
> = Depth extends MaxDepth
|
||||||
|
? T
|
||||||
|
: T extends readonly unknown[]
|
||||||
|
? Simple<T[number], Inc<Depth>>
|
||||||
|
: T;
|
||||||
|
|
||||||
|
export type Flatten<
|
||||||
|
T extends readonly unknown[],
|
||||||
|
TOrig extends readonly unknown[] = T,
|
||||||
|
TOut extends unknown[] = [],
|
||||||
|
> = TOut["length"] extends MaxDepth
|
||||||
|
? Flat.Simple<TOrig>[]
|
||||||
|
: T extends readonly [infer Current, ...infer Rest]
|
||||||
|
? Current extends readonly unknown[]
|
||||||
|
? number extends Current["length"]
|
||||||
|
? Flatten<Rest, TOrig, [...TOut, ...Current]>
|
||||||
|
: Flatten<
|
||||||
|
Rest,
|
||||||
|
TOrig,
|
||||||
|
[...TOut, ...Flat<Current>]
|
||||||
|
>
|
||||||
|
: Flatten<Rest, TOrig, [...TOut, Current]>
|
||||||
|
: T extends readonly []
|
||||||
|
? TOut
|
||||||
|
: never;
|
||||||
|
export type Flat<
|
||||||
|
T extends readonly unknown[],
|
||||||
|
TOrig extends readonly unknown[] = T,
|
||||||
|
> = number extends T["length"]
|
||||||
|
? Flat.Simple<T>[]
|
||||||
|
: Flat.Flatten<T, TOrig>;
|
||||||
|
}
|
||||||
|
export type Flat<T extends readonly unknown[]> = Flat.Flat<T>;
|
||||||
|
|
||||||
|
if (import.meta.vitest) {
|
||||||
|
const { test, expectTypeOf } = import.meta.vitest;
|
||||||
|
|
||||||
|
test("Vec<T, N>", () => {
|
||||||
|
expectTypeOf<Vec<never, 0>>().toEqualTypeOf<[]>();
|
||||||
|
|
||||||
|
expectTypeOf<Vec<number, 4>>().toEqualTypeOf<
|
||||||
|
[number, number, number, number]
|
||||||
|
>();
|
||||||
|
expectTypeOf<Vec<number, 4, true>>().toEqualTypeOf<
|
||||||
|
readonly [number, number, number, number]
|
||||||
|
>();
|
||||||
|
|
||||||
|
expectTypeOf<Vec<number, typeof Infinity>>().toEqualTypeOf<
|
||||||
|
number[]
|
||||||
|
>();
|
||||||
|
expectTypeOf<Vec<number, number>>().toEqualTypeOf<number[]>();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Inc<N>", () => {
|
||||||
|
expectTypeOf<Inc<0>>().toEqualTypeOf<1>();
|
||||||
|
expectTypeOf<Inc<50>>().toEqualTypeOf<51>();
|
||||||
|
|
||||||
|
expectTypeOf<Inc<-5>>().toEqualTypeOf<number>();
|
||||||
|
expectTypeOf<Inc<typeof Infinity>>().toEqualTypeOf<number>();
|
||||||
|
expectTypeOf<Inc<number>>().toEqualTypeOf<number>();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Dec<N>", () => {
|
||||||
|
expectTypeOf<Dec<5>>().toEqualTypeOf<4>();
|
||||||
|
expectTypeOf<Dec<0>>().toEqualTypeOf<-1>();
|
||||||
|
expectTypeOf<Dec<-4>>().toEqualTypeOf<-5>();
|
||||||
|
|
||||||
|
expectTypeOf<Dec<typeof Infinity>>().toEqualTypeOf<number>();
|
||||||
|
expectTypeOf<Dec<number>>().toEqualTypeOf<number>();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("At<T, N>", () => {
|
||||||
|
type Array = [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
expectTypeOf<At<Array, 0>>().toEqualTypeOf<Array[0]>();
|
||||||
|
expectTypeOf<At<Array, -1>>().toEqualTypeOf<Array[5]>();
|
||||||
|
|
||||||
|
expectTypeOf<At<Array, 10>>().toEqualTypeOf<undefined>();
|
||||||
|
expectTypeOf<At<Array, -10>>().toEqualTypeOf<undefined>();
|
||||||
|
expectTypeOf<At<number[], 0>>().toEqualTypeOf<
|
||||||
|
number | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
expectTypeOf<At<Array, [0, -1]>>().toEqualTypeOf<[0, 5]>();
|
||||||
|
expectTypeOf<At<Readonly<Array>, [0]>>().toEqualTypeOf<[0]>();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Flat<T>", () => {
|
||||||
|
type Array = [0, [1, 2], [[3]]];
|
||||||
|
|
||||||
|
expectTypeOf<Flat<Array>>().toEqualTypeOf<[0, 1, 2, 3]>();
|
||||||
|
expectTypeOf<Flat<number[]>>().toEqualTypeOf<number[]>();
|
||||||
|
|
||||||
|
expectTypeOf<Flat<[...Array, boolean[]]>>().toEqualTypeOf<
|
||||||
|
[0, 1, 2, 3, ...boolean[]]
|
||||||
|
>();
|
||||||
|
|
||||||
|
expectTypeOf<Flat<number[][][]>>().toEqualTypeOf<number[]>();
|
||||||
|
expectTypeOf<
|
||||||
|
Flat<((number[] | number)[] | number)[]>
|
||||||
|
>().toEqualTypeOf<number[]>();
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user