spica
Version:
Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.
293 lines (273 loc) • 13 kB
text/typescript
import { isArray, toString, ObjectGetPrototypeOf } from './alias';
export type NonNull = {};
type Falsy = undefined | false | 0 | 0n | '' | null | void;
type Unique = typeof Unique;
declare const Unique: unique symbol;
export type Not<T extends boolean> = T extends true ? false : true;
export type And<TS extends readonly unknown[]> =
TS extends readonly [infer T1] ? T1 :
TS extends readonly [infer T1, ...infer TS] ? [T1] extends [Falsy] ? T1 : And<TS> :
never;
export type Or<TS extends readonly unknown[]> =
TS extends readonly [infer T1] ? T1 :
TS extends readonly [infer T1, ...infer TS] ? [T1] extends [Falsy] ? Or<TS> : T1 :
never;
export type IsNever<T> = [T] extends [never] ? true : false;
export type IsVoid<T> = [void] extends [T] ? Not<Or<[IsAny<T>, IsUnknown<T>]>> : false;
export type IsAny<T> = [T] extends [Unique] ? Not<IsNever<T>> : false;
export type IsUnknown<T> = [T] extends [Unique | {} | void | null] ? false : true;
export type Eq<T, U> =
// Exclude never type from T and U.
Or<[IsNever<T>, IsNever<U>]> extends true ? And<[IsNever<T>, IsNever<U>]> :
// T and U below are a type except never.
// Distribute U.
U extends never
// Never reach here.
? never :
// Compare distributed T and U.
T extends U ? U extends T ? true : false : false;
export type TEq<T, U> =
Or<[IsAny<T>, IsAny<U>]> extends true ? And<[IsAny<T>, IsAny<U>]> :
[T] extends [U] ? [U] extends [T] ? true : false : false;
export type If<S, T, U> = S extends Falsy ? U : T;
export type Case<T extends keyof U, U extends {}> = U[T];
export type DEq<T extends ValueOf<NondeterminateTypeMap>, U extends ValueOf<NondeterminateTypeMap>> =
Determine<T> extends undefined ? undefined :
Determine<U> extends undefined ? undefined :
Eq<T, U>;
type Determine<T extends ValueOf<NondeterminateTypeMap>> =
ValueOf<NondeterminateTypeMap> extends T ? undefined :
T;
interface NondeterminateTypeMap {
boolean: boolean;
}
export type Narrow<TS extends readonly unknown[]> = Narrow_<TS, [], []>;
type Narrow_<TS extends readonly unknown[], US extends TS[number][], VS extends TS[number][]> =
TS extends readonly [] ? [US, VS] extends [[infer U1, ...infer _], []] ? [U1] : VS :
TS extends readonly [infer T1, ...infer TS] ?
[T1] extends [never] ? TS extends [] ? VS : Narrow_<TS, US, VS> :
[Extract<TS[number] | US[number], T1>] extends [never] ? Narrow_<TS, [...US, T1], [...VS, T1]> :
Narrow_<TS, [...US, T1], VS> :
never;
export type Intersect<TS extends readonly unknown[]> =
TS extends readonly [infer T] ? T :
TS extends readonly [infer T, ...infer TS] ? T & Intersect<TS> :
never;
// 型計算中の編集により不正な計算結果が出力されるため実用不可(再入不可)
export type StrToNum<T extends string> =
T extends `-${number}` ? never :
T extends `${number}` ? StringToNumber<T> : never;
type StringToNumber<T extends `${number}`, as extends 0[] = []> =
T extends keyof [0, ...as] ? as['length'] : StringToNumber<T, [0, ...as]>;
export type Head<as extends readonly unknown[]> =
as extends readonly [infer a, ...unknown[]] ? a :
never;
export type Tail<as extends readonly unknown[]> =
as extends readonly [unknown, ...infer as] ? as :
never;
export type Init<as extends readonly unknown[]> =
as extends readonly [...infer a, unknown] ? a :
never;
export type Last<as extends readonly unknown[]> =
as extends readonly [...unknown[], infer a] ? a :
never;
export type Inits<as extends readonly unknown[]> =
number extends as['length'] ? never :
as extends readonly [] ? [] :
as | Inits<Init<as>>;
export type Tails<as extends readonly unknown[]> =
number extends as['length'] ? never :
as extends readonly [] ? [] :
as | Tails<Tail<as>>;
export type Index<a, as extends readonly unknown[]> = Idx<a, as, []>;
type Idx<a, as extends readonly unknown[], bs extends readonly void[]> =
TEq<Readonly<as>, Readonly<Tail<as> | as>> extends true ? -1 :
If<TEq<as[0], a>, bs['length'], Idx<a, Tail<as>, [void, ...bs]>>;
export type Member<a, as extends readonly unknown[]> = Index<a, as> extends -1 ? false : true;
export type Reverse<as extends readonly unknown[]> =
as extends readonly [infer a, ...infer as] ? [...Reverse<as>, a] :
as;
export type Filter<TS extends readonly unknown[], ES extends readonly unknown[] = []> =
TS extends readonly [] ? [] :
TS extends readonly [infer T1, ...infer TS] ?
If<Member<T1, ES>, Filter<TS, ES>, [T1, ...Filter<TS, ES>]> :
If<Member<TS[number], ES>, ExactExclude<TS[number], ES[number]>[], TS>;
export type TupleIndex<as extends readonly unknown[]> =
number extends as['length'] ? number :
as extends [unknown, ...infer as] ? TupleIdx<as> :
never;
type TupleIdx<as extends readonly unknown[], bs extends readonly unknown[] = as extends [unknown, ...infer bs] ? bs : never> =
bs extends readonly unknown[] ? bs['length'] | TupleIdx<bs> :
never;
export type Rewrite<T, R extends [unknown, unknown]> =
[T] extends [never]
? true extends (R extends never ? never : R[0] extends never ? true : never)
? R extends (R extends never ? never : R[0] extends never ? R : never) ? R[1] : never
: T :
T extends never ? never :
true extends (R extends never ? never : T extends R[0] ? true : never)
? R extends (R extends never ? never : T extends R[0] ? R : never) ? R[1] : never
: T;
export type ExactRewrite<T, R extends [unknown, unknown]> =
[T] extends [never] ? Rewrite<T, R> :
T extends never ? never :
true extends (R extends never ? never : If<Eq<T, R[0]>, true, never>)
? R extends (R extends never ? never : If<Eq<T, R[0]>, R, never>) ? R[1] : never
: T;
export type ExactExtract<T, U> = T extends U ? U extends T ? T : never : never;
export type ExactExclude<T, U> = T extends ExactExtract<T, U> ? never : T;
export type IndexOf<T, V extends ValueOf<T>> =
T extends readonly unknown[] ? Index<V, T> :
{ [P in keyof T]: If<TEq<T[P], V>, P, never>; }[keyof T];
export type ValueOf<T, K extends string | number | symbol = T extends { [i: number]: unknown; length: number; } ? number : keyof T> = T[Extract<keyof T, K>];
export type Type<T> =
T extends void ? null extends void ? 'object' | 'undefined' : 'undefined' :
T extends undefined ? 'undefined' :
T extends boolean ? 'boolean' :
T extends number ? 'number' :
T extends bigint ? 'bigint' :
T extends string ? 'string' :
T extends symbol ? 'symbol' :
T extends Function ? 'function' :
'object';
export type StrictType<T> =
IsNever<T> extends true ? 'never' :
IsAny<T> extends true ? 'any' :
IsUnknown<T> extends true ? 'unknown' :
IsVoid<T> extends true ? 'void' :
T extends null ? 'null' :
Type<T>;
export type Pick<T, K extends string | number | symbol> = { [P in Extract<keyof T, K>]: T[P]; };
export type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; };
export type Structural<T, K extends number | string | symbol = number | string> = Pick<T, K>;
export type OverwriteStruct<T, U> = Pick<Omit<T, keyof U> & U, any>;
export type ExtractProp<T, V> =
{ [Q in { [P in keyof T]: T[P] extends never ? If<TEq<V, never>, P, never> : T[P] extends V ? P : never; }[keyof T]]: T[Q]; };
export type DeepExtractProp<T, V, E = never> =
T extends E ? never :
T extends V ? T :
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends readonly unknown[] | Function ? never :
T extends object ? ExcludeProp<{ [Q in { [P in keyof T]: If<TEq<V, never>, T[P] extends never ? P : never, T[P] extends V | object ? T[P] extends E ? never : P : never>; }[keyof T]]: ExactExclude<DeepExtractProp<T[Q], V, E>, {}>; }, never> :
never;
export type ExcludeProp<T, V> =
{ [Q in { [P in keyof T]: If<TEq<V, never>, T[P] extends never ? never : P, If<Includes<T[P], V>, never, P>>; }[keyof T]]: T[Q]; };
export type DeepExcludeProp<T, V, E = never> =
T extends E ? T :
T extends V ? never :
T extends readonly unknown[] | Function ? T :
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends object ? ExcludeProp<{ [Q in { [P in keyof T]: If<TEq<V, never>, T[P] extends never ? P : P, If<Includes<T[P], V>, T[P] extends E ? P : never, P>>; }[keyof T]]: ExactExclude<DeepExcludeProp<T[Q], V, E>, {}>; }, never> :
T;
export type RewriteProp<T, R extends [unknown, unknown]> =
{ [P in keyof T]: Rewrite<T[P], R>; };
export type DeepRewriteProp<T, R extends [unknown, unknown], E = never> =
[T] extends [never] ? Rewrite<T, R> :
T extends E ? T :
true extends (R extends never ? never : T extends R[0] ? true : never) ? Rewrite<T, R> :
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends readonly unknown[] | Function ? T :
T extends object ? ExcludeProp<{ [P in keyof T]: DeepRewriteProp<T[P], R, E>; }, never> :
T;
type Includes<T, U> = true extends (T extends U ? true : never) ? true : false;
export type Partial<T> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
{ [P in keyof T]+?: T[P]; };
export type DeepPartial<T, E = readonly unknown[]> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends E | Function ? T :
{ [P in keyof T]+?: DeepPartial<T[P], E>; };
export type Required<T> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
{ [P in keyof T]-?: T[P]; };
export type DeepRequired<T, E = readonly unknown[]> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends E | Function ? T :
{ [P in keyof T]-?: DeepRequired<T[P], E>; };
export type Immutable<T> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends ReadonlySet<infer V> ? ReadonlySet<V> :
T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<K, V> :
T extends ReadonlyArray<infer V> ? TEq<T, V[]> extends true ? readonly V[] :
{ readonly [P in keyof T]: T[P]; } :
{ readonly [P in keyof T]: T[P]; };
export type DeepImmutable<T, E = never> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends E | Function ? T :
T extends ReadonlySet<infer V> ? ReadonlySet<V> :
T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<K, V> :
T extends ReadonlyArray<infer V> ? TEq<T, V[]> extends true ? readonly V[] :
{ readonly [P in keyof T]: DeepImmutable<T[P], E>; } :
{ readonly [P in keyof T]: DeepImmutable<T[P], E>; };
export type Mutable<T> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends ReadonlySet<infer V> ? Set<V> :
T extends ReadonlyMap<infer K, infer V> ? Map<K, V> :
T extends ReadonlyArray<infer V> ? TEq<T, readonly V[]> extends true ? V[] :
{ -readonly [P in keyof T]: T[P]; } :
{ -readonly [P in keyof T]: T[P]; };
export type DeepMutable<T, E = never> =
Or<[IsAny<T>, IsUnknown<T>]> extends true ? T :
T extends E | Function ? T :
T extends ReadonlySet<infer V> ? Set<V> :
T extends ReadonlyMap<infer K, infer V> ? Map<K, V> :
T extends ReadonlyArray<infer V> ? TEq<T, readonly V[]> extends true ? V[] :
{ -readonly [P in keyof T]: DeepMutable<T[P], E>; } :
{ -readonly [P in keyof T]: DeepMutable<T[P], E>; };
const ObjectPrototype = Object.prototype;
const ArrayPrototype = Array.prototype;
export function type(value: unknown): string {
const type = typeof value;
switch (type) {
case 'function':
return 'Function';
case 'object':
if (value === null) return 'null';
const tag: string = (value as object)[Symbol.toStringTag];
if (tag) return tag;
switch (ObjectGetPrototypeOf(value)) {
case ArrayPrototype:
return 'Array';
case ObjectPrototype:
return 'Object';
default:
return value?.constructor?.name || toString(value).slice(8, -1);
}
default:
return type;
}
}
export function is(type: 'undefined', value: unknown): value is undefined;
export function is(type: 'null', value: unknown): value is null;
export function is(type: 'boolean', value: unknown): value is boolean;
export function is(type: 'number', value: unknown): value is number;
export function is(type: 'bigint', value: unknown): value is bigint;
export function is(type: 'string', value: unknown): value is string;
export function is(type: 'symbol', value: unknown): value is symbol;
export function is(type: 'function', value: unknown): value is Function;
export function is(type: 'object', value: unknown): value is object;
export function is(type: 'array', value: unknown[]): value is unknown[];
export function is(type: 'array', value: unknown): value is readonly unknown[];
export function is(type: string, value: unknown): boolean {
switch (type) {
case 'null':
return value === null;
case 'array':
return isArray(value);
case 'object':
return value !== null && typeof value === type;
default:
return typeof value === type;
}
}
export type Primitive = undefined | null | boolean | number | bigint | string | symbol;
export function isPrimitive(value: unknown): value is Primitive {
switch (typeof value) {
case 'function':
return false;
case 'object':
return value === null;
default:
return true;
}
}