@kakasoo/proto-typescript
Version:
Utility types and implementations based on JavaScript prototypes.
135 lines • 8.77 kB
TypeScript
import { NeverType } from './never.type';
import { NumberType } from './number.type';
import { Equal, ObjectType } from './object.type';
import { Primitive, ReadonlyOrNot } from './primitive.type';
export declare namespace ArrayType {
export type TypePredicate<Container extends ReadonlyOrNot<any[]>, Target> = {
<Index extends number, __Target extends Target = Target>(value?: ArrayType.At<Container, Index>, index?: Index, array?: Container): value is Target;
};
/**
* @todo don't use `Equal` type and use `includes` of `union types` ( make `union incldues` type )
*/
export type Filter<T extends ReadonlyOrNot<any[]>, Target> = T extends [infer First, ...infer Rest] ? Equal<First, Target> extends true ? [First, ...Filter<Rest, Target>] : Filter<Rest, Target> : [];
type _FilterNull<FilterNull extends boolean, Target> = FilterNull extends true ? Equal<Target, null> extends true ? never : Target : Target;
type _FilterUndefined<FilterUndefined extends boolean, Target> = FilterUndefined extends true ? Equal<Target, undefined> extends true ? never : Target : Target;
/**
* type a = ArrayType.Filter<[1, 2, true, 3, undefined, null, 5], true, true> // [1, 2, 3, 5]
*/
export type FilterNullish<T extends ReadonlyOrNot<any[]>, AllowNull extends boolean, AllowUndefined extends boolean> = IsTuple<T> extends false ? Exclude<ElementOf<T>, (AllowNull extends true ? null : never) | (AllowUndefined extends true ? undefined : never)>[] : T extends [infer First, ...infer Rest] ? NeverType.IsNever<_FilterNull<AllowNull, First>> extends true ? FilterNullish<Rest, AllowNull, AllowUndefined> : NeverType.IsNever<_FilterUndefined<AllowUndefined, First>> extends true ? FilterNullish<Rest, AllowNull, AllowUndefined> : [First, ...FilterNullish<Rest, AllowNull, AllowUndefined>] : [];
/**
* Get length of tuple or string literal type.
*/
export type Length<T extends ReadonlyOrNot<any[]>> = T['length'];
export type Push<T extends ReadonlyOrNot<any[]>, V extends any> = [...T, V];
export type Concat<T extends ReadonlyOrNot<any[]>, P extends ReadonlyOrNot<any[]>> = [...T, ...P];
export type ElementOf<Tuple extends ReadonlyOrNot<any[]>> = [...Tuple] extends (infer E)[] ? E : never;
export type Values<T extends ReadonlyOrNot<any[]>> = T[number];
export type TupleToUnion<T extends NTuple<number>> = T[number];
export type Take<T extends ReadonlyOrNot<any[]>, P extends number, R extends ReadonlyOrNot<any[]> = []> = ArrayType.Length<R> extends P ? R : T extends [infer F, ...infer Rest] ? Take<Rest, P, ArrayType.Push<R, F>> : R;
export type Slice<T extends ReadonlyOrNot<any[]>, Start extends number, End extends number> = SliceByValue<T, T[Start], NeverType.IsNever<End> extends true ? never : T[End]>;
/**
* Returns matching A to matching B in tuple form.
* If there are no elements that match A or B, then never type.
*/
export type SliceByValue<T extends ReadonlyOrNot<any[]>, A extends any, B extends any, CONDITION extends boolean = false> = T extends [infer X, ...infer Rest] ? CONDITION extends true ? X extends B ? [X, ...SliceByValue<Rest, A, B, false>] : [X, ...SliceByValue<Rest, A, B, true>] : X extends A ? X extends B ? [X, ...SliceByValue<Rest, A, B, false>] : [X, ...SliceByValue<Rest, A, B, true>] : SliceByValue<Rest, A, B, false> : CONDITION extends true ? [] : [];
export type At<Tuple extends ReadonlyOrNot<any[]>, Index extends number> = Tuple[Index];
/**
* If any of the type elements constituting Union Type U correspond to `If`, it returns true or false.
*/
export type UnionSome<If, U, T, F> = T extends (U extends If ? T : F) ? T : F;
/**
* If any of the type elements constituting Tuple Type U correspond to `If`, it returns true or false.
*/
export type Some<Target, Tuple extends ReadonlyOrNot<any[]>> = UnionSome<Target, Tuple[number], true, false> | boolean;
export type Includes<T extends ReadonlyOrNot<any[]>, U> = T extends [infer P, ...infer R] ? Equal<U, P> extends true ? true : Includes<R, U> : false;
/**
* Join<['a', 'b', 'c']> // 'abc'
* Join<['a', 'b', 'c'], '-'> // 'a-b-c'
* Join<string[], "-">; // string
* Join<['a', 'b', 'c', true], '-'>; // 'a-b-c-true'
* Join<['a', 'b', 'c', number], '-'>; // 'a-b-c-${number}'
*/
export type Join<T extends ReadonlyOrNot<Exclude<Primitive, symbol>[]>, U extends string = ','> = T extends readonly [
infer F extends Exclude<Primitive, symbol>,
...infer Rest extends ReadonlyOrNot<Exclude<Primitive, symbol>[]>
] ? Rest extends [] ? `${F}` : `${F}${U}${Join<Rest, U>}` : string;
export type IsTuple<T extends ReadonlyOrNot<any[]> | {
length: number;
}> = [T] extends [never] ? false : T extends ReadonlyOrNot<any[]> ? number extends T['length'] ? false : true : false;
/**
* Reverse<[1,2,3]> // [3,2,1]
*/
export type Reverse<T extends ReadonlyOrNot<any[]>> = T extends [infer F, ...infer Rest] ? [...Reverse<Rest>, F] : [];
/**
* Shift<[1,2,3]> // [2,3]
*/
export type Shift<T extends ReadonlyOrNot<any[]>, N extends number> = T extends [
...infer F extends NTuple<N>,
...infer Rest
] ? Rest : [];
/**
* Unshift<[1, 2, 3], 4> // [4,1,2,3]
*/
export type Unshift<T extends ReadonlyOrNot<any[]>, V> = [V, ...T];
/**
* Pop<[1,2,3]> // [1,2]
*/
export type Pop<T extends ReadonlyOrNot<any[]>> = T extends [...infer Rest, infer Last] ? Rest : [];
/**
* 튜플에서 중복 요소를 제거하는 타입
*
* Distinct<[1,1,2,2,3,3,3,4]> // [1,2,3,4]
*/
export type Distinct<T extends ReadonlyOrNot<any[]>, P extends ReadonlyOrNot<any[]> = []> = T extends [
infer F,
...infer Rest
] ? Includes<P, F> extends false ? Distinct<Rest, [...P, F]> : Distinct<Rest, P> : P;
export type EntriesToObject<T extends Array<NTuple<2>>> = T extends [infer F, ...infer Rest] ? F extends [infer K extends string, infer V] ? Rest extends NTuple<2>[] ? ObjectType.Merge<Record<K, V>, EntriesToObject<Rest>> : never : never : {};
/**
* PartitionByTwo<[1,2,3,4,5,6,7,8]> // [[1,2],[3,4],[5,6],[7,8]]
*/
export type PartitionByTwo<T extends ReadonlyOrNot<any[]>, L extends number = ArrayType.Length<T>> = T extends [
infer First,
infer Second,
...infer Rest
] ? [[First, Second], ...PartitionByTwo<Rest, NumberType.Sub<L, 2>>] : [];
export type BubbleSort<T extends ReadonlyOrNot<any[]>, L extends number = ArrayType.Length<T>> = L extends 1 ? T : T extends [infer F, infer S, ...infer Rest] ? BubbleSort<[
...(NumberType.Compare<NumberType.NToNumber<F>, '>=', NumberType.NToNumber<S>> extends false ? [F, ...BubbleSort<[S, ...Rest], NumberType.Sub<L, 1>>] : [S, ...BubbleSort<[F, ...Rest], NumberType.Sub<L, 1>>])
], NumberType.Sub<L, 1>> : never;
/**
* 사칙연산을 튜플에 적용한 타입
*
* type a = Map<[3, 4, 5], "Add", 2>; // [5, 6, 7]
* type b = Map<[3, 4, 5], "Multiply", 2>; // [6, 8, 10]
* type c = Map<[3, 4, 5], "Sub", 2>; // [1, 2, 3]
* type d = Map<[3, 4, 5], "Divide", 2>; // [1, 2, 2]
* type e = Map<[3, 4, 5], "Remainder", 2>; // [1, 0, 1]
*/
export type Map<T extends readonly number[], OP extends 'Add' | 'Multiply' | 'Sub' | 'Divide' | 'Remainder', N extends number> = OP extends 'Add' ? {
[K in keyof T]: NumberType.Add<T[K], N>;
} : OP extends 'Multiply' ? {
[K in keyof T]: NumberType.Multiply<T[K], N>;
} : OP extends 'Sub' ? {
[K in keyof T]: NumberType.Sub<T[K], N>;
} : OP extends 'Divide' ? {
[K in keyof T]: NumberType.Divide<T[K], N>;
} : OP extends 'Remainder' ? {
[K in keyof T]: NumberType.Remainder<T[K], N>;
} : never;
export {};
}
/**
* 현재 튜플 형태에 새로운 타입 하나를 추가하는 타입
*
* Push<[], any> // [any]
* Push<[], 1> // [1]
*/
export type NTuple<N extends number, T extends ReadonlyOrNot<any[]> = [], defaultType = any> = T['length'] extends N ? T : NTuple<N, ArrayType.Push<T, defaultType>>;
/**
* N1 * N2 크기의 NTuple을 반환하는 타입으로, 최적화를 위해 N1, N2 숫자를 비교하는 과정이 포함된 타입
*
* NNTuple<2,3> = [...NTuple<3>, ...NTuple<3>]
* NNTuple<3,2> = [...NTuple<3>, ...NTuple<3>]
*/
export type NNTuple<N1 extends number, N2 extends number> = [NumberType.Sub<N1, N2>] extends [never] ? NumberType.Sub<N1, 1> extends never ? [] : [...NNTuple<NumberType.Sub<N1, 1>, N2>, ...NTuple<N2>] : NumberType.Sub<N2, 1> extends never ? [] : [...NNTuple<NumberType.Sub<N2, 1>, N1>, ...NTuple<N1>];
//# sourceMappingURL=array.type.d.ts.map