UNPKG

spica

Version:

Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.

690 lines (591 loc) 30.3 kB
import { Not, And, Or, IsNever, IsVoid, IsAny, IsUnknown, Eq, TEq, DEq, If, Case, Narrow, Intersect, Head, Tail, Init, Last, Inits, Tails, Index, Member, Reverse, Filter, Rewrite, ExactRewrite, ExactExtract, ExactExclude, ValueOf, IndexOf, Type, StrictType, OverwriteStruct, ExtractProp, DeepExtractProp, ExcludeProp, DeepExcludeProp, RewriteProp, DeepRewriteProp, Partial, DeepPartial, Required, DeepRequired, Immutable, DeepImmutable, Mutable, DeepMutable, type, is, } from './type'; import { Cache } from './cache'; import { AtomicPromise } from './promise'; import { AtomicFuture } from './future'; describe('Unit: lib/type', () => { describe('Not', () => { it('', () => { assert((): true => true as TEq<Not<true>, false>); assert((): true => true as TEq<Not<false>, true>); }); }); describe('And', () => { it('', () => { assert((): true => true as TEq<And<[true, true]>, true>); assert((): true => true as TEq<And<[true, false]>, false>); assert((): true => true as TEq<And<[false, true]>, false>); assert((): true => true as TEq<And<[false, false]>, false>); assert((): true => true as TEq<And<[true, undefined]>, undefined>); assert((): true => true as TEq<And<[false, undefined]>, false>); assert((): true => true as TEq<And<[undefined, true]>, undefined>); assert((): true => true as TEq<And<[undefined, false]>, undefined>); assert((): true => true as TEq<And<[0, 1]>, 0>); assert((): true => true as TEq<And<['', 1]>, ''>); assert((): true => true as TEq<And<[null, 1]>, null>); assert((): true => true as TEq<And<[void, 1]>, void>); assert((): true => true as TEq<And<[never, 1]>, never>); assert((): true => true as TEq<And<[0, never]>, 0>); assert((): true => true as TEq<And<[1, never]>, never>); }); }); describe('Or', () => { it('', () => { assert((): true => true as TEq<Or<[true, true]>, true>); assert((): true => true as TEq<Or<[true, false]>, true>); assert((): true => true as TEq<Or<[false, true]>, true>); assert((): true => true as TEq<Or<[false, false]>, false>); assert((): true => true as TEq<Or<[never, true]>, true>); assert((): true => true as TEq<Or<[never, false]>, false>); assert((): true => true as TEq<Or<[true, never]>, true>); assert((): true => true as TEq<Or<[false, never]>, never>); }); }); describe('IsNever', () => { it('', () => { assert((): true => true as TEq<IsNever<never>, true>); assert((): true => true as TEq<IsNever<void>, false>); assert((): true => true as TEq<IsNever<any>, false>); assert((): true => true as TEq<IsNever<unknown>, false>); assert((): true => true as TEq<IsNever<{}>, false>); }); }); describe('IsVoid', () => { it('', () => { assert((): true => true as TEq<IsVoid<never>, false>); assert((): true => true as TEq<IsVoid<void>, true>); assert((): true => true as TEq<IsVoid<any>, false>); assert((): true => true as TEq<IsVoid<unknown>, false>); assert((): true => true as TEq<IsVoid<{}>, false>); assert((): true => true as TEq<IsVoid<undefined>, false>); assert((): true => true as TEq<IsVoid<null>, false>); assert((): true => true as TEq<IsVoid<0>, false>); assert((): true => true as TEq<IsVoid<object>, false>); }); }); describe('IsAny', () => { it('', () => { assert((): true => true as TEq<IsAny<never>, false>); assert((): true => true as TEq<IsAny<void>, false>); assert((): true => true as TEq<IsAny<any>, true>); assert((): true => true as TEq<IsAny<unknown>, false>); assert((): true => true as TEq<IsAny<{}>, false>); }); }); describe('IsUnknown', () => { it('', () => { assert((): true => true as TEq<IsUnknown<never>, false>); assert((): true => true as TEq<IsUnknown<void>, false>); assert((): true => true as TEq<IsUnknown<any>, false>); assert((): true => true as TEq<IsUnknown<unknown>, true>); assert((): true => true as TEq<IsUnknown<{}>, false>); assert((): true => true as TEq<IsUnknown<undefined>, false>); assert((): true => true as TEq<IsUnknown<null>, false>); assert((): true => true as TEq<IsUnknown<0>, false>); assert((): true => true as TEq<IsUnknown<object>, false>); }); }); describe('Eq', () => { it('', () => { assert((): true => true as TEq<Eq<true, true>, true>); assert((): true => true as TEq<Eq<true, false>, false>); assert((): true => true as TEq<Eq<false, true>, false>); assert((): true => true as TEq<Eq<false, false>, true>); assert((): true => true as TEq<Eq<boolean, true>, boolean>); assert((): true => true as TEq<Eq<boolean, false>, boolean>); assert((): true => true as TEq<Eq<boolean, boolean>, boolean>); assert((): true => true as TEq<Eq<0, 0>, true>); assert((): true => true as TEq<Eq<0, number>, false>); assert((): true => true as TEq<Eq<number, 0>, false>); assert((): true => true as TEq<Eq<number, number>, true>); assert((): true => true as TEq<Eq<void, void>, true>); assert((): true => true as TEq<Eq<void, undefined>, false>); assert((): true => true as TEq<Eq<void, null>, false>); assert((): true => true as TEq<Eq<void, undefined | null>, false>); assert((): true => true as TEq<Eq<void, never>, false>); assert((): true => true as TEq<Eq<never, never>, true>); assert((): true => true as TEq<Eq<never, void>, false>); assert((): true => true as TEq<Eq<never, undefined>, false>); assert((): true => true as TEq<Eq<never, null>, false>); assert((): true => true as TEq<Eq<{}, [] | {}>, boolean>); assert((): true => true as TEq<Eq<[] | {}, {}>, boolean>); }); }); describe('TEq', () => { it('', () => { assert((): true => true as TEq<true, true>); assert((): false => true as TEq<true, false>); assert((): false => true as TEq<false, true>); assert((): true => true as TEq<false, false>); assert((): false => true as TEq<true, boolean>); assert((): false => true as TEq<false, boolean>); assert((): false => true as TEq<boolean, true>); assert((): false => true as TEq<boolean, false>); assert((): true => true as TEq<boolean, boolean>); assert((): false => true as TEq<boolean, never>); assert((): false => true as TEq<never, boolean>); assert((): true => true as TEq<never, never>); assert((): true => true as TEq<any, any>); assert((): false => true as TEq<any, unknown>); assert((): false => true as TEq<any, never>); assert((): false => true as TEq<unknown, any>); assert((): false => true as TEq<[], [] | {}>); assert((): false => true as TEq<[] | {}, []>); assert((): true => true as TEq<{}, [] | {}>); assert((): true => true as TEq<[] | {}, {}>); }); }); describe('DEq', () => { it('', () => { assert((): true => true as TEq<DEq<true, true>, true>); assert((): true => true as TEq<DEq<true, false>, false>); assert((): true => true as TEq<DEq<true, boolean>, undefined>); assert((): true => true as TEq<DEq<false, true>, false>); assert((): true => true as TEq<DEq<false, false>, true>); assert((): true => true as TEq<DEq<false, boolean>, undefined>); assert((): true => true as TEq<DEq<boolean, boolean>, undefined>); }); }); describe('If', () => { it('', () => { assert((): true => true as TEq<If<true, 1, 0>, 1>); assert((): true => true as TEq<If<false, 1, 0>, 0>); assert((): true => true as TEq<If<0, 1, 0>, 0>); assert((): true => true as TEq<If<1, 1, 0>, 1>); }); }); describe('Case', () => { it('', () => { assert((): true => true as TEq<Case<0, [1]>, 1>); assert((): true => true as TEq<Case<0, { 0: 1 }>, 1>); assert((): true => true as TEq<Case<1, { 0: 1; [otherwise: string]: number; }>, number>); }); }); describe('Narrow', () => { it('', () => { assert((): true => true as TEq<Narrow<[]>, []>); assert((): true => true as TEq<Narrow<[never]>, []>); assert((): true => true as TEq<Narrow<[any]>, [any]>); assert((): true => true as TEq<Narrow<[unknown]>, [unknown]>); assert((): true => true as TEq<Narrow<[void]>, [void]>); assert((): true => true as TEq<Narrow<[void, undefined]>, [undefined]>); assert((): true => true as TEq<Narrow<[0]>, [0]>); assert((): true => true as TEq<Narrow<[0, any]>, [0]>); assert((): true => true as TEq<Narrow<[0, never]>, [0]>); assert((): true => true as TEq<Narrow<[0, unknown]>, [0]>); assert((): true => true as TEq<Narrow<[0, void]>, [0, void]>); assert((): true => true as TEq<Narrow<[0, undefined]>, [0, undefined]>); assert((): true => true as TEq<Narrow<[0, 1]>, [0, 1]>); assert((): true => true as TEq<Narrow<[0, number]>, [0]>); assert((): true => true as TEq<Narrow<[0, number]>, [0]>); assert((): true => true as TEq<Narrow<[0, string, number]>, [0, string]>); assert((): true => true as TEq<Narrow<[number, number]>, [number]>); assert((): true => true as TEq<Narrow<[number, string, 0]>, [string, 0]>); }); }); describe('Intersect', () => { it('', () => { assert((): true => true as TEq<Intersect<[]>, never>); assert((): true => true as TEq<Intersect<[0]>, 0>); assert((): true => true as TEq<Intersect<[0, 1]>, never>); assert((): true => true as TEq<Intersect<[0, number]>, 0>); }); }); describe('Head', () => { it('', () => { assert((): true => true as TEq<Head<[]>, never>); assert((): true => true as TEq<Head<[0]>, 0>); assert((): true => true as TEq<Head<[0, 1]>, 0>); assert((): true => true as TEq<Head<number[]>, never>); assert((): true => true as TEq<Head<[0, 1, ...number[]]>, 0>); }); }); describe('Tail', () => { it('', () => { assert((): true => true as TEq<Tail<[]>, never>); assert((): true => true as TEq<Tail<[0]>, []>); assert((): true => true as TEq<Tail<[0, 1]>, [1]>); assert((): true => true as TEq<Tail<number[]>, never>); assert((): true => true as TEq<Tail<[0, 1, ...number[]]>, [1, ...number[]]>); }); }); describe('Init', () => { it('', () => { assert((): true => true as TEq<Init<[]>, never>); assert((): true => true as TEq<Init<[0]>, []>); assert((): true => true as TEq<Init<[0, 1]>, [0]>); assert((): true => true as TEq<Init<number[]>, never>); assert((): true => true as TEq<Init<[0, 1, ...number[]]>, never>); }); }); describe('Last', () => { it('', () => { assert((): true => true as TEq<Last<[]>, never>); assert((): true => true as TEq<Last<[0]>, 0>); assert((): true => true as TEq<Last<[0, 1]>, 1>); assert((): true => true as TEq<Last<number[]>, never>); assert((): true => true as TEq<Last<[0, 1, ...number[]]>, never>); }); }); describe('Inits', () => { it('', () => { assert((): true => true as TEq<Inits<[]>, []>); assert((): true => true as TEq<Inits<[0]>, [0] | []>); assert((): true => true as TEq<Inits<[0, 1]>, [0, 1] | [0] | []>); assert((): true => true as TEq<Inits<number[]>, never>); assert((): true => true as TEq<Inits<[0, 1, ...number[]]>, never>); }); }); describe('Tails', () => { it('', () => { assert((): true => true as TEq<Tails<[]>, []>); assert((): true => true as TEq<Tails<[0]>, [0] | []>); assert((): true => true as TEq<Tails<[0, 1]>, [0, 1] | [1] | []>); assert((): true => true as TEq<Tails<number[]>, never>); assert((): true => true as TEq<Tails<[0, 1, ...number[]]>, never>); }); }); describe('Index', () => { it('', () => { assert((): true => true as TEq<Index<0, []>, -1>); assert((): true => true as TEq<Index<0, [0]>, 0>); assert((): true => true as TEq<Index<0, [0, 1]>, 0>); assert((): true => true as TEq<Index<1, [0, 1]>, 1>); assert((): true => true as TEq<Index<2, [0, 1]>, -1>); assert((): true => true as TEq<Index<0, 0[]>, -1>); assert((): true => true as TEq<Index<0, 1[]>, -1>); assert((): true => true as TEq<Index<0, [0, ...0[]]>, 0>); }); }); describe('Member', () => { it('', () => { assert((): true => true as TEq<Member<0, []>, false>); assert((): true => true as TEq<Member<0, [0]>, true>); assert((): true => true as TEq<Member<0, [0, 1]>, true>); assert((): true => true as TEq<Member<1, [0, 1]>, true>); assert((): true => true as TEq<Member<2, [0, 1]>, false>); assert((): true => true as TEq<Member<0, 0[]>, false>); assert((): true => true as TEq<Member<0, 1[]>, false>); }); }); describe('Reverse', () => { it('', () => { assert((): true => true as TEq<Reverse<[]>, []>); assert((): true => true as TEq<Reverse<[0]>, [0]>); assert((): true => true as TEq<Reverse<[0, 1]>, [1, 0]>); assert((): true => true as TEq<Reverse<[0, 1, 2]>, [2, 1, 0]>); assert((): true => true as TEq<Reverse<number[]>, number[]>); }); }); describe('Filter', () => { it('', () => { assert((): true => true as TEq<Filter<[], []>, []>); assert((): true => true as TEq<Filter<[], [0]>, []>); assert((): true => true as TEq<Filter<[0], []>, [0]>); assert((): true => true as TEq<Filter<[0], [0]>, []>); assert((): true => true as TEq<Filter<[0], [1]>, [0]>); assert((): true => true as TEq<Filter<[0, 1], []>, [0, 1]>); assert((): true => true as TEq<Filter<[0, 1], [0]>, [1]>); assert((): true => true as TEq<Filter<[0, 1], [1]>, [0]>); assert((): true => true as TEq<Filter<[0, 1], [0, 1]>, []>); assert((): true => true as TEq<Filter<[0, 1, 2], []>, [0, 1, 2]>); assert((): true => true as TEq<Filter<[0, 1, 2], [1]>, [0, 2]>); assert((): true => true as TEq<Filter<0[], []>, 0[]>); assert((): true => true as TEq<Filter<0[], [0]>, never[]>); assert((): true => true as TEq<Filter<[0, ...0[]], []>, [0, ...0[]]>); assert((): true => true as TEq<Filter<[0, ...0[]], [0]>, never[]>); assert((): true => true as TEq<Filter<[0, ...1[]], [0]>, 1[]>); assert((): true => true as TEq<Filter<[0, ...1[]], [1]>, [0, ...never[]]>); }); }); describe('Rewrite', () => { it('', () => { assert((): true => true as TEq<Rewrite<1, [1, -1]>, -1>); assert((): true => true as TEq<Rewrite<1, [1, -1] | [0, 0]>, -1>); assert((): true => true as TEq<Rewrite<0 | 1, [1, -1]>, 0 | -1>); assert((): true => true as TEq<Rewrite<0 | 1, [1, -1] | [0, void]>, void | -1>); assert((): true => true as TEq<Rewrite<void, [void, never]>, never>); assert((): true => true as TEq<Rewrite<never, [never, void]>, void>); }); }); describe('ExactRewrite', () => { it('', () => { assert((): true => true as TEq<ExactRewrite<[] | {}, [{}, void]>, [] | void>); assert((): true => true as TEq<ExactRewrite<0, [never, 1]>, 0>); }); }); describe('ExactExtract', () => { it('', () => { assert((): true => true as TEq<ExactExtract<[] | {}, {} | null>, {}>); assert((): true => true as TEq<ExactExtract<0, never>, never>); }); }); describe('ExactExclude', () => { it('', () => { assert((): true => true as TEq<ExactExclude<[] | {}, {} | null>, []>); assert((): true => true as TEq<ExactExclude<0, never>, 0>); }); }); describe('IndexOf', () => { it('', () => { assert((): true => true as TEq<IndexOf<[0, -1], -1>, 1>); assert((): true => true as TEq<IndexOf<{ 0: 0; 1: -1 }, -1>, 1>); }); }); describe('ValueOf', () => { it('', () => { assert((): true => true as TEq<ValueOf<{ 0: 0; a: 1; }>, 0 | 1>); assert((): true => true as TEq<ValueOf<{ 0: 0; a: 1; }, 0>, 0>); assert((): true => true as TEq<ValueOf<[0]>, 0>); assert((): true => true as TEq<ValueOf<{ [i: number]: 0; }>, 0>); assert((): true => true as TEq<ValueOf<Immutable<{ 0: 0; a: 1; }>>, 0 | 1>); assert((): true => true as TEq<ValueOf<ReadonlyArray<0>>, 0>); }); }); describe('Type', () => { it('', () => { assert((): true => true as TEq<Type<void>, 'undefined'>); assert((): true => true as TEq<Type<undefined>, 'undefined'>); assert((): true => true as TEq<Type<boolean>, 'boolean'>); assert((): true => true as TEq<Type<number>, 'number'>); assert((): true => true as TEq<Type<bigint>, 'bigint'>); assert((): true => true as TEq<Type<string>, 'string'>); assert((): true => true as TEq<Type<symbol>, 'symbol'>); assert((): true => true as TEq<Type<() => unknown>, 'function'>); assert((): true => true as TEq<Type<(arg: unknown) => unknown>, 'function'>); assert((): true => true as TEq<Type<(...args: unknown[]) => unknown>, 'function'>); assert((): true => true as TEq<Type<() => unknown>, 'function'>); assert((): true => true as TEq<Type<new () => unknown>, 'function'>); assert((): true => true as TEq<Type<new (arg: unknown) => unknown>, 'function'>); assert((): true => true as TEq<Type<new (...args: unknown[]) => unknown>, 'function'>); assert((): true => true as TEq<Type<unknown[]>, 'object'>); assert((): true => true as TEq<Type<object>, 'object'>); assert((): true => true as TEq<Type<null>, 'object'>); assert((): true => true as TEq<StrictType<never>, 'never'>); assert((): true => true as TEq<StrictType<any>, 'any'>); assert((): true => true as TEq<StrictType<unknown>, 'unknown'>); assert((): true => true as TEq<StrictType<void>, 'void'>); assert((): true => true as TEq<StrictType<undefined>, 'undefined'>); assert((): true => true as TEq<StrictType<null>, 'null'>); }); }); describe('OverwriteStruct', () => { it('', () => { type AB = { a: boolean; b: boolean; }; type B = { b: number; }; type Expected = { a: boolean; b: number; }; assert((): true => true as TEq<OverwriteStruct<AB, B>, Expected>); }); }); describe('ExtractProp', () => { it('', () => { type AB = { a: boolean; b: boolean | undefined; }; type A = { a: boolean; }; assert((): true => true as TEq<ExtractProp<AB, boolean>, A>); assert((): true => true as TEq<ExtractProp<AB, boolean | number>, A>); assert((): true => true as TEq<ExtractProp<AB, never>, {}>); assert((): true => true as TEq<ExtractProp<{ a: never; b: void; }, never>, { a: never; }>); assert((): true => true as TEq<ExtractProp<{ a: never; b: void; }, void>, { b: void; }>); }); }); describe('DeepExtractProp', () => { it('', () => { type AD = { a: boolean; b: { a: boolean; b: boolean[]; c: undefined; d: undefined[]; e: boolean | undefined; f: Array<boolean | undefined>; }; c: { a: undefined; }; }; assert((): true => true as TEq<DeepExtractProp<AD, boolean>, { a: boolean; b: { a: boolean; }; }>); assert((): true => true as TEq<DeepExtractProp<AD, boolean | boolean[]>, { a: boolean; b: { a: boolean; b: boolean[]; }; }>); assert((): true => true as TEq<DeepExtractProp<AD, boolean, AD['b']>, { a: boolean; }>); assert((): true => true as TEq<DeepExtractProp<{ a: { b: { c: 0; d: 0 | 1; e: 1; }; }; }, 0>, { a: { b: { c: 0; }; }; }>); assert((): true => true as TEq<DeepExtractProp<{ a: Function; }, never>, {}>); assert((): true => true as TEq<DeepExtractProp<{ a: never; b: void; }, never>, {}>); assert((): true => true as TEq<DeepExtractProp<{ a: never; b: void; }, void>, { b: void; }>); }); }); describe('ExcludeProp', () => { it('', () => { type AB = { a: boolean; b: boolean | undefined; }; type A = { a: boolean; }; assert((): true => true as TEq<ExcludeProp<AB, undefined>, A>); assert((): true => true as TEq<ExcludeProp<AB, undefined | number>, A>); assert((): true => true as TEq<ExcludeProp<AB, never>, AB>); assert((): true => true as TEq<ExcludeProp<{ a: never; b: void; }, never>, { b: void; }>); assert((): true => true as TEq<ExcludeProp<{ a: never; b: void; }, void>, { a: never; }>); }); }); describe('DeepExcludeProp', () => { it('', () => { type AD = { a: boolean; b: { a: boolean; b: boolean[]; c: undefined; d: undefined[]; e: boolean | undefined; f: Array<boolean | undefined>; }; c: { a: undefined; }; }; assert((): true => true as TEq<DeepExcludeProp<AD, undefined>, { a: boolean; b: { a: boolean; b: boolean[]; d: undefined[]; f: Array<boolean | undefined>; }; }>); assert((): true => true as TEq<DeepExcludeProp<AD, undefined | undefined[]>, { a: boolean; b: { a: boolean; b: boolean[]; f: Array<boolean | undefined>; }; }>); assert((): true => true as TEq<DeepExcludeProp<AD, undefined, AD['b']>, ExcludeProp<AD, AD['c']>>); assert((): true => true as TEq<DeepExcludeProp<{ a: { b: { c: 0; d: 0 | 1; e: 1; }; }; }, 0>, { a: { b: { e: 1; }; }; }>); assert((): true => true as TEq<DeepExcludeProp<{ a: Function; }, never>, { a: Function; }>); assert((): true => true as TEq<DeepExcludeProp<{ a: never; b: void; }, never>, { b: void; }>); assert((): true => true as TEq<DeepExcludeProp<{ a: never; b: void; }, void>, {}>); }); }); describe('RewriteProp', () => { it('', () => { type A = { a: boolean; b: undefined; }; type B = { a: boolean; b: number; }; assert((): true => true as TEq<RewriteProp<A, [undefined, number]>, B>); assert((): true => true as TEq<RewriteProp<A, [undefined | number, number]>, B>); assert((): true => true as TEq<RewriteProp<A, [boolean, number] | [undefined, never]>, { a: number; b: never; }>); assert((): true => true as TEq<RewriteProp<A, [never, never]>, A>); assert((): true => true as TEq<RewriteProp<{ a: never; b: void; }, [never, null]>, { a: null; b: void; }>); assert((): true => true as TEq<RewriteProp<{ a: never; b: void; }, [void, null]>, { a: never; b: null; }>); }); }); describe('DeepRewriteProp', () => { it('', () => { type A = { a: { a: boolean; b: undefined; c: undefined[]; }; }; type B = { a: { a: boolean; b: number; c: undefined[]; }; }; assert((): true => true as TEq<DeepRewriteProp<A, [undefined, number]>, B>); assert((): true => true as TEq<DeepRewriteProp<A, [undefined | number, number]>, B>); assert((): true => true as TEq<DeepRewriteProp<A, [boolean, number] | [undefined, never]>, { a: { a: number; c: undefined[]; }; }>); assert((): true => true as TEq<DeepRewriteProp<A, [never, never]>, A>); assert((): true => true as TEq<DeepRewriteProp<{ a: { b: { c: 0; d: 0 | 1; e: 1; }; }; }, [1, -1]>, { a: { b: { c: 0; d: 0 | -1; e: -1; }; }; }>); assert((): true => true as TEq<DeepExcludeProp<{ a: Function; }, [0, 0]>, { a: Function; }>); assert((): true => true as TEq<DeepRewriteProp<{ a: never; b: void; }, [never, null]>, { a: null; b: void; }>); assert((): true => true as TEq<DeepRewriteProp<{ a: never; b: void; }, [void, null]>, { b: null; }>); }); }); describe('Partial', () => { it('', () => { type R = { a: number[]; b: { c: string; }; d: () => 0; e: new () => object }; type P = { a?: number[]; b?: { c: string; }; d?: () => 0; e?: new () => object }; assert((): true => true as TEq<Partial<never>, never>); assert((): true => true as TEq<Partial<any>, any>); assert((): true => true as TEq<Partial<unknown>, unknown>); assert((): true => true as TEq<Partial<R>, P>); assert((): true => true as TEq<Partial<Required<R>>, P>); }); }); describe('DeepPartial', () => { it('', () => { type R = { a: number; b: { c: string[]; d: () => 0; e: new () => object }; }; type P = { a?: number; b?: { c?: string[]; d?: () => 0; e?: new () => object }; }; assert((): true => true as TEq<DeepPartial<never>, never>); assert((): true => true as TEq<DeepPartial<any>, any>); assert((): true => true as TEq<DeepPartial<unknown>, unknown>); assert((): true => true as TEq<DeepPartial<R>, P>); assert((): true => true as TEq<DeepPartial<DeepRequired<R>>, P>); assert((): true => true as TEq<DeepPartial<R, R['b']>, Partial<R>>); }); }); describe('Required', () => { it('', () => { type R = { a: number[]; b: { c?: string; }; d: () => 0; e: new () => object }; type P = { a?: number[]; b?: { c?: string; }; d?: () => 0; e?: new () => object }; assert((): true => true as TEq<Required<never>, never>); assert((): true => true as TEq<Required<any>, any>); assert((): true => true as TEq<Required<unknown>, unknown>); assert((): true => true as TEq<Required<P>, R>); assert((): true => true as TEq<Required<Partial<R>>, R>); }); }); describe('DeepRequired', () => { it('', () => { type R = { a: number; b: { c: string[]; d: () => 0; e: new () => object }; }; type P = { a?: number; b?: { c?: string[]; d?: () => 0; e?: new () => object }; }; assert((): true => true as TEq<DeepRequired<never>, never>); assert((): true => true as TEq<DeepRequired<any>, any>); assert((): true => true as TEq<DeepRequired<unknown>, unknown>); assert((): true => true as TEq<DeepRequired<P>, R>); assert((): true => true as TEq<DeepRequired<DeepPartial<R>>, R>); assert((): true => true as TEq<DeepRequired<P, P['b']>, Required<P>>); }); }); describe('Immutable', () => { it('', () => { type I = { readonly a?: [number]; readonly b: { c: string; }; readonly d: () => 0; readonly e: new () => object, f: Set<number>, g: ReadonlySet<number> }; type M = { a?: [number]; b: { c: string; }; d: () => 0; e: new () => object, f: Set<number>, g: ReadonlySet<number> }; assert((): true => true as TEq<Immutable<never>, never>); assert((): true => true as TEq<Immutable<any>, any>); assert((): true => true as TEq<Immutable<unknown>, unknown>); assert((): true => true as TEq<Immutable<M>, I>); assert((): true => true as TEq<Immutable<unknown[]>, ReadonlyArray<unknown>>); assert((): true => true as TEq<Immutable<{ a: unknown }>, { readonly a: unknown }>); }); }); describe('DeepImmutable', () => { it('', () => { type I = { readonly a?: number; readonly b: { readonly c: readonly [string]; readonly d: () => 0; readonly e: new () => object, f: ReadonlySet<number>, g: ReadonlySet<number> }; }; type M = { a?: number; b: { c: [string]; d: () => 0; e: new () => object, f: Set<number>, g: ReadonlySet<number> }; }; assert((): true => true as TEq<DeepImmutable<never>, never>); assert((): true => true as TEq<DeepImmutable<any>, any>); assert((): true => true as TEq<DeepImmutable<unknown>, unknown>); assert((): true => true as TEq<DeepImmutable<M>, I>); assert((): true => true as TEq<DeepImmutable<M, M['b']>, Immutable<M>>); assert((): true => true as TEq<DeepImmutable<unknown[]>, ReadonlyArray<unknown>>); assert((): true => true as TEq<DeepImmutable<{ a: unknown[] }>, { readonly a: readonly unknown[] }>); }); }); describe('Mutable', () => { it('', () => { type I = { readonly a?: [number]; readonly b: { c: string; }; readonly d: () => 0; readonly e: new () => object, f: Set<number>, g: ReadonlySet<number> }; type M = { a?: [number]; b: { c: string; }; d: () => 0; e: new () => object, f: Set<number>, g: ReadonlySet<number> }; assert((): true => true as TEq<Mutable<never>, never>); assert((): true => true as TEq<Mutable<any>, any>); assert((): true => true as TEq<Mutable<unknown>, unknown>); assert((): true => true as TEq<Mutable<I>, M>); assert((): true => true as TEq<Mutable<readonly unknown[]>, unknown[]>); assert((): true => true as TEq<Mutable<{ readonly a: unknown }>, { a: unknown }>); }); }); describe('DeepMutable', () => { it('', () => { type I = { readonly a?: number; readonly b: { readonly c: readonly [string]; readonly d: () => 0; readonly e: new () => object, f: ReadonlySet<number>, g: ReadonlySet<number> }; }; type M = { a?: number; b: { c: [string]; d: () => 0; e: new () => object, f: Set<number>, g: Set<number> }; }; assert((): true => true as TEq<DeepMutable<never>, never>); assert((): true => true as TEq<DeepMutable<any>, any>); assert((): true => true as TEq<DeepMutable<unknown>, unknown>); assert((): true => true as TEq<DeepMutable<I>, M>); assert((): true => true as TEq<DeepMutable<I, I['b']>, Mutable<I>>); assert((): true => true as TEq<DeepMutable<readonly unknown[]>, unknown[]>); assert((): true => true as TEq<DeepMutable<{ readonly a: readonly unknown[] }>, { a: unknown[] }>); }); }); describe('type', () => { it('primitive', () => { assert(type(undefined) === 'undefined'); assert(type(false) === 'boolean'); assert(type(0) === 'number'); assert(type('') === 'string'); assert(type(Symbol()) === 'symbol'); assert(type(null) === 'null'); }); it('object', () => { assert(type([]) === 'Array'); assert(type({}) === 'Object'); assert(type(Object.create(null)) === 'Object'); assert(type(Object.create({})) === 'Object'); assert(type(() => 0) === 'Function'); assert(type(new Boolean()) === 'Boolean'); assert(type(new WeakMap()) === 'WeakMap'); assert(type(new Cache(1)) === 'Cache'); assert(type(AtomicPromise.resolve()) === 'Promise'); assert(type(new AtomicFuture()) === 'Promise'); }); }); describe('is', () => { it('', () => { assert(is('undefined', undefined)); assert(is('null', null)); assert(is('function', () => 0)); assert(is('object', {})); assert(is('array', [])); }); }); });