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 true ? false : true; export type And = TS extends readonly [infer T1] ? T1 : TS extends readonly [infer T1, ...infer TS] ? [T1] extends [Falsy] ? T1 : And : never; export type Or = TS extends readonly [infer T1] ? T1 : TS extends readonly [infer T1, ...infer TS] ? [T1] extends [Falsy] ? Or : T1 : never; export type IsNever = [T] extends [never] ? true : false; export type IsVoid = [void] extends [T] ? Not, IsUnknown]>> : false; export type IsAny = [T] extends [Unique] ? Not> : false; export type IsUnknown = [T] extends [Unique | {} | void | null] ? false : true; export type Eq = // Exclude never type from T and U. Or<[IsNever, IsNever]> extends true ? And<[IsNever, IsNever]> : // 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 = Or<[IsAny, IsAny]> extends true ? And<[IsAny, IsAny]> : [T] extends [U] ? [U] extends [T] ? true : false : false; export type If = S extends Falsy ? U : T; export type Case = U[T]; export type DEq, U extends ValueOf> = Determine extends undefined ? undefined : Determine extends undefined ? undefined : Eq; type Determine> = ValueOf extends T ? undefined : T; interface NondeterminateTypeMap { boolean: boolean; } export type Narrow = Narrow_; type Narrow_ = 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_ : [Extract] extends [never] ? Narrow_ : Narrow_ : never; export type Intersect = TS extends readonly [infer T] ? T : TS extends readonly [infer T, ...infer TS] ? T & Intersect : never; // 型計算中の編集により不正な計算結果が出力されるため実用不可(再入不可) export type StrToNum = T extends `-${number}` ? never : T extends `${number}` ? StringToNumber : never; type StringToNumber = T extends keyof [0, ...as] ? as['length'] : StringToNumber; export type Head = as extends readonly [infer a, ...unknown[]] ? a : never; export type Tail = as extends readonly [unknown, ...infer as] ? as : never; export type Init = as extends readonly [...infer a, unknown] ? a : never; export type Last = as extends readonly [...unknown[], infer a] ? a : never; export type Inits = number extends as['length'] ? never : as extends readonly [] ? [] : as | Inits>; export type Tails = number extends as['length'] ? never : as extends readonly [] ? [] : as | Tails>; export type Index = Idx; type Idx = TEq, Readonly | as>> extends true ? -1 : If, bs['length'], Idx, [void, ...bs]>>; export type Member = Index extends -1 ? false : true; export type Reverse = as extends readonly [infer a, ...infer as] ? [...Reverse, a] : as; export type Filter = TS extends readonly [] ? [] : TS extends readonly [infer T1, ...infer TS] ? If, Filter, [T1, ...Filter]> : If, ExactExclude[], TS>; export type TupleIndex = number extends as['length'] ? number : as extends [unknown, ...infer as] ? TupleIdx : never; type TupleIdx = bs extends readonly unknown[] ? bs['length'] | TupleIdx : never; export type Rewrite = [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] extends [never] ? Rewrite : T extends never ? never : true extends (R extends never ? never : If, true, never>) ? R extends (R extends never ? never : If, R, never>) ? R[1] : never : T; export type ExactExtract = T extends U ? U extends T ? T : never : never; export type ExactExclude = T extends ExactExtract ? never : T; export type IndexOf> = T extends readonly unknown[] ? Index : { [P in keyof T]: If, P, never>; }[keyof T]; export type ValueOf = T[Extract]; export type Type = 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 = IsNever extends true ? 'never' : IsAny extends true ? 'any' : IsUnknown extends true ? 'unknown' : IsVoid extends true ? 'void' : T extends null ? 'null' : Type; export type Pick = { [P in Extract]: T[P]; }; export type Omit = { [P in Exclude]: T[P]; }; export type Structural = Pick; export type OverwriteStruct = Pick & U, any>; export type ExtractProp = { [Q in { [P in keyof T]: T[P] extends never ? If, P, never> : T[P] extends V ? P : never; }[keyof T]]: T[Q]; }; export type DeepExtractProp = T extends E ? never : T extends V ? T : Or<[IsAny, IsUnknown]> extends true ? T : T extends readonly unknown[] | Function ? never : T extends object ? ExcludeProp<{ [Q in { [P in keyof T]: If, T[P] extends never ? P : never, T[P] extends V | object ? T[P] extends E ? never : P : never>; }[keyof T]]: ExactExclude, {}>; }, never> : never; export type ExcludeProp = { [Q in { [P in keyof T]: If, T[P] extends never ? never : P, If, never, P>>; }[keyof T]]: T[Q]; }; export type DeepExcludeProp = T extends E ? T : T extends V ? never : T extends readonly unknown[] | Function ? T : Or<[IsAny, IsUnknown]> extends true ? T : T extends object ? ExcludeProp<{ [Q in { [P in keyof T]: If, T[P] extends never ? P : P, If, T[P] extends E ? P : never, P>>; }[keyof T]]: ExactExclude, {}>; }, never> : T; export type RewriteProp = { [P in keyof T]: Rewrite; }; export type DeepRewriteProp = [T] extends [never] ? Rewrite : T extends E ? T : true extends (R extends never ? never : T extends R[0] ? true : never) ? Rewrite : Or<[IsAny, IsUnknown]> extends true ? T : T extends readonly unknown[] | Function ? T : T extends object ? ExcludeProp<{ [P in keyof T]: DeepRewriteProp; }, never> : T; type Includes = true extends (T extends U ? true : never) ? true : false; export type Partial = Or<[IsAny, IsUnknown]> extends true ? T : { [P in keyof T]+?: T[P]; }; export type DeepPartial = Or<[IsAny, IsUnknown]> extends true ? T : T extends E | Function ? T : { [P in keyof T]+?: DeepPartial; }; export type Required = Or<[IsAny, IsUnknown]> extends true ? T : { [P in keyof T]-?: T[P]; }; export type DeepRequired = Or<[IsAny, IsUnknown]> extends true ? T : T extends E | Function ? T : { [P in keyof T]-?: DeepRequired; }; export type Immutable = Or<[IsAny, IsUnknown]> extends true ? T : T extends ReadonlySet ? ReadonlySet : T extends ReadonlyMap ? ReadonlyMap : T extends ReadonlyArray ? TEq extends true ? readonly V[] : { readonly [P in keyof T]: T[P]; } : { readonly [P in keyof T]: T[P]; }; export type DeepImmutable = Or<[IsAny, IsUnknown]> extends true ? T : T extends E | Function ? T : T extends ReadonlySet ? ReadonlySet : T extends ReadonlyMap ? ReadonlyMap : T extends ReadonlyArray ? TEq extends true ? readonly V[] : { readonly [P in keyof T]: DeepImmutable; } : { readonly [P in keyof T]: DeepImmutable; }; export type Mutable = Or<[IsAny, IsUnknown]> extends true ? T : T extends ReadonlySet ? Set : T extends ReadonlyMap ? Map : T extends ReadonlyArray ? TEq extends true ? V[] : { -readonly [P in keyof T]: T[P]; } : { -readonly [P in keyof T]: T[P]; }; export type DeepMutable = Or<[IsAny, IsUnknown]> extends true ? T : T extends E | Function ? T : T extends ReadonlySet ? Set : T extends ReadonlyMap ? Map : T extends ReadonlyArray ? TEq extends true ? V[] : { -readonly [P in keyof T]: DeepMutable; } : { -readonly [P in keyof T]: DeepMutable; }; 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; } }