925 - Assert Array Index
Opened this issue · 0 comments
koSakano commented
type Num = ReadonlyArray<0>;
type N0 = readonly [];
type N1 = readonly [0];
type N2 = readonly [0, 0];
type N3 = readonly [0, 0, 0];
type N4 = readonly [0, 0, 0, 0];
type N5 = readonly [0, 0, 0, 0, 0];
type N6 = readonly [0, 0, 0, 0, 0, 0];
type N7 = readonly [0, 0, 0, 0, 0, 0, 0];
type N8 = readonly [0, 0, 0, 0, 0, 0, 0, 0];
type N9 = readonly [0, 0, 0, 0, 0, 0, 0, 0, 0];
/**
* Sum<N3, N4> = N7.
*/
type Sum<N extends Num, M extends Num> = readonly [...N, ...M];
type NA = Sum<N9, N7>;
type NI = Sum<NA, Sum<N9, N5>>;
type NP = Sum<NI, Sum<N9, N8>>;
type NX = Sum<NP, Sum<N9, N4>>;
type Codes = {
' ': N7;
a: Sum<NA, N1>;
b: Sum<NA, N2>;
c: Sum<NA, N3>;
d: Sum<NA, N4>;
e: Sum<NA, N5>;
f: Sum<NA, N6>;
g: Sum<NA, N7>;
h: Sum<NA, N8>;
i: Sum<NI, N1>;
j: Sum<NI, N2>;
k: Sum<NI, N3>;
l: Sum<NI, N4>;
m: Sum<NI, N5>;
n: Sum<NI, N6>;
o: Sum<NI, N7>;
p: Sum<NP, N1>;
q: Sum<NP, N2>;
r: Sum<NP, N3>;
s: Sum<NP, N4>;
t: Sum<NP, N5>;
u: Sum<NP, N6>;
v: Sum<NP, N7>;
w: Sum<NP, N9>;
x: Sum<NX, N1>;
y: Sum<NX, N2>;
z: Sum<NX, N3>;
};
/**
* KeyToNum<'ab'> = N74.
*/
type KeyToNum<Key extends string> = Key extends ''
? N0
: Key extends `${infer L}${infer Rest}`
? L extends keyof Codes
? Sum<Codes[L], KeyToNum<Rest>>
: never
: never;
/**
* IsArray<[0]> = false, IsArray<string[]> = true.
*/
type IsArray<A extends readonly unknown[]> = number extends A['length'] ? true : false;
/**
* IsKey<'ab x'> = true, IsKey<'key!'> = false.
*/
type IsKey<Key extends string> = Key extends ''
? false
: KeyToNum<Key> extends never
? false
: true;
declare const KEY: unique symbol;
declare const CODE: unique symbol;
/**
* WithIndex<string, 'foo'> = object with key index 'foo'.
*/
type WithIndex<
Element,
Key extends string,
KeyCode extends number = KeyToNum<Key>['length']
> = KeyCode extends never
? never
: {
readonly [KEY]: Key;
readonly [CODE]: KeyCode;
} & {
readonly [K in KeyCode]: Element;
};
/**
* Index<typeof indexedArray> = index of indexedArray.
*/
type Index<A extends { readonly [CODE]: number }> = A[typeof CODE];
/**
* assertArrayIndex(arr, 'foo') assert that arr is array with key index 'foo'.
*/
function assertArrayIndex<A extends readonly unknown[], Key extends string>(
array: IsKey<Key> extends true ? (IsArray<A> extends true ? A : never) : never,
key: Key,
): asserts array is IsKey<Key> extends true
? IsArray<A> extends true
? A & WithIndex<A[number], Key>
: never
: never {}