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, false>); assert((): true => true as TEq, true>); }); }); describe('And', () => { it('', () => { assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, undefined>); assert((): true => true as TEq, false>); assert((): true => true as TEq, undefined>); assert((): true => true as TEq, undefined>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, ''>); assert((): true => true as TEq, null>); assert((): true => true as TEq, void>); assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, never>); }); }); describe('Or', () => { it('', () => { assert((): true => true as TEq, true>); assert((): true => true as TEq, true>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, never>); }); }); describe('IsNever', () => { it('', () => { assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); }); }); describe('IsVoid', () => { it('', () => { assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); }); }); describe('IsAny', () => { it('', () => { assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); }); }); describe('IsUnknown', () => { it('', () => { assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); }); }); describe('Eq', () => { it('', () => { assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, boolean>); assert((): true => true as TEq, boolean>); assert((): true => true as TEq, boolean>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, boolean>); assert((): true => true as TEq, boolean>); }); }); describe('TEq', () => { it('', () => { assert((): true => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): true => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): true => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): true => true as TEq); assert((): true => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); assert((): false => true as TEq); 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, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, undefined>); assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, undefined>); assert((): true => true as TEq, undefined>); }); }); describe('If', () => { it('', () => { assert((): true => true as TEq, 1>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 1>); }); }); describe('Case', () => { it('', () => { assert((): true => true as TEq, 1>); assert((): true => true as TEq, 1>); assert((): true => true as TEq, number>); }); }); describe('Narrow', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [any]>); assert((): true => true as TEq, [unknown]>); assert((): true => true as TEq, [void]>); assert((): true => true as TEq, [undefined]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0, void]>); assert((): true => true as TEq, [0, undefined]>); assert((): true => true as TEq, [0, 1]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0, string]>); assert((): true => true as TEq, [number]>); assert((): true => true as TEq, [string, 0]>); }); }); describe('Intersect', () => { it('', () => { assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); }); }); describe('Head', () => { it('', () => { assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); }); }); describe('Tail', () => { it('', () => { assert((): true => true as TEq, never>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [1]>); assert((): true => true as TEq, never>); assert((): true => true as TEq, [1, ...number[]]>); }); }); describe('Init', () => { it('', () => { assert((): true => true as TEq, never>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, never>); assert((): true => true as TEq, never>); }); }); describe('Last', () => { it('', () => { assert((): true => true as TEq, never>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 1>); assert((): true => true as TEq, never>); assert((): true => true as TEq, never>); }); }); describe('Inits', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, [0] | []>); assert((): true => true as TEq, [0, 1] | [0] | []>); assert((): true => true as TEq, never>); assert((): true => true as TEq, never>); }); }); describe('Tails', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, [0] | []>); assert((): true => true as TEq, [0, 1] | [1] | []>); assert((): true => true as TEq, never>); assert((): true => true as TEq, never>); }); }); describe('Index', () => { it('', () => { assert((): true => true as TEq, -1>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 1>); assert((): true => true as TEq, -1>); assert((): true => true as TEq, -1>); assert((): true => true as TEq, -1>); assert((): true => true as TEq, 0>); }); }); describe('Member', () => { it('', () => { assert((): true => true as TEq, false>); assert((): true => true as TEq, true>); assert((): true => true as TEq, true>); assert((): true => true as TEq, true>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); assert((): true => true as TEq, false>); }); }); describe('Reverse', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [1, 0]>); assert((): true => true as TEq, [2, 1, 0]>); assert((): true => true as TEq, number[]>); }); }); describe('Filter', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, [0, 1]>); assert((): true => true as TEq, [1]>); assert((): true => true as TEq, [0]>); assert((): true => true as TEq, []>); assert((): true => true as TEq, [0, 1, 2]>); assert((): true => true as TEq, [0, 2]>); assert((): true => true as TEq, 0[]>); assert((): true => true as TEq, never[]>); assert((): true => true as TEq, [0, ...0[]]>); assert((): true => true as TEq, never[]>); assert((): true => true as TEq, 1[]>); assert((): true => true as TEq, [0, ...never[]]>); }); }); describe('Rewrite', () => { it('', () => { assert((): true => true as TEq, -1>); assert((): true => true as TEq, -1>); assert((): true => true as TEq, 0 | -1>); assert((): true => true as TEq, void | -1>); assert((): true => true as TEq, never>); assert((): true => true as TEq, void>); }); }); describe('ExactRewrite', () => { it('', () => { assert((): true => true as TEq, [] | void>); assert((): true => true as TEq, 0>); }); }); describe('ExactExtract', () => { it('', () => { assert((): true => true as TEq, {}>); assert((): true => true as TEq, never>); }); }); describe('ExactExclude', () => { it('', () => { assert((): true => true as TEq, []>); assert((): true => true as TEq, 0>); }); }); describe('IndexOf', () => { it('', () => { assert((): true => true as TEq, 1>); assert((): true => true as TEq, 1>); }); }); describe('ValueOf', () => { it('', () => { assert((): true => true as TEq, 0 | 1>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 0>); assert((): true => true as TEq, 0>); assert((): true => true as TEq>, 0 | 1>); assert((): true => true as TEq>, 0>); }); }); describe('Type', () => { it('', () => { assert((): true => true as TEq, 'undefined'>); assert((): true => true as TEq, 'undefined'>); assert((): true => true as TEq, 'boolean'>); assert((): true => true as TEq, 'number'>); assert((): true => true as TEq, 'bigint'>); assert((): true => true as TEq, 'string'>); assert((): true => true as TEq, 'symbol'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq unknown>, 'function'>); assert((): true => true as TEq, 'object'>); assert((): true => true as TEq, 'object'>); assert((): true => true as TEq, 'object'>); assert((): true => true as TEq, 'never'>); assert((): true => true as TEq, 'any'>); assert((): true => true as TEq, 'unknown'>); assert((): true => true as TEq, 'void'>); assert((): true => true as TEq, 'undefined'>); assert((): true => true as TEq, '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, Expected>); }); }); describe('ExtractProp', () => { it('', () => { type AB = { a: boolean; b: boolean | undefined; }; type A = { a: boolean; }; assert((): true => true as TEq, A>); assert((): true => true as TEq, A>); assert((): true => true as TEq, {}>); assert((): true => true as TEq, { a: never; }>); assert((): true => true as TEq, { b: void; }>); }); }); describe('DeepExtractProp', () => { it('', () => { type AD = { a: boolean; b: { a: boolean; b: boolean[]; c: undefined; d: undefined[]; e: boolean | undefined; f: Array; }; c: { a: undefined; }; }; assert((): true => true as TEq, { a: boolean; b: { a: boolean; }; }>); assert((): true => true as TEq, { a: boolean; b: { a: boolean; b: boolean[]; }; }>); assert((): true => true as TEq, { a: boolean; }>); assert((): true => true as TEq, { a: { b: { c: 0; }; }; }>); assert((): true => true as TEq, {}>); assert((): true => true as TEq, {}>); assert((): true => true as TEq, { b: void; }>); }); }); describe('ExcludeProp', () => { it('', () => { type AB = { a: boolean; b: boolean | undefined; }; type A = { a: boolean; }; assert((): true => true as TEq, A>); assert((): true => true as TEq, A>); assert((): true => true as TEq, AB>); assert((): true => true as TEq, { b: void; }>); assert((): true => true as TEq, { a: never; }>); }); }); describe('DeepExcludeProp', () => { it('', () => { type AD = { a: boolean; b: { a: boolean; b: boolean[]; c: undefined; d: undefined[]; e: boolean | undefined; f: Array; }; c: { a: undefined; }; }; assert((): true => true as TEq, { a: boolean; b: { a: boolean; b: boolean[]; d: undefined[]; f: Array; }; }>); assert((): true => true as TEq, { a: boolean; b: { a: boolean; b: boolean[]; f: Array; }; }>); assert((): true => true as TEq, ExcludeProp>); assert((): true => true as TEq, { a: { b: { e: 1; }; }; }>); assert((): true => true as TEq, { a: Function; }>); assert((): true => true as TEq, { b: void; }>); assert((): true => true as TEq, {}>); }); }); describe('RewriteProp', () => { it('', () => { type A = { a: boolean; b: undefined; }; type B = { a: boolean; b: number; }; assert((): true => true as TEq, B>); assert((): true => true as TEq, B>); assert((): true => true as TEq, { a: number; b: never; }>); assert((): true => true as TEq, A>); assert((): true => true as TEq, { a: null; b: void; }>); assert((): true => true as TEq, { 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, B>); assert((): true => true as TEq, B>); assert((): true => true as TEq, { a: { a: number; c: undefined[]; }; }>); assert((): true => true as TEq, A>); assert((): true => true as TEq, { a: { b: { c: 0; d: 0 | -1; e: -1; }; }; }>); assert((): true => true as TEq, { a: Function; }>); assert((): true => true as TEq, { a: null; b: void; }>); assert((): true => true as TEq, { 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, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, P>); assert((): true => true as TEq>, 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, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, P>); assert((): true => true as TEq>, P>); assert((): true => true as TEq, Partial>); }); }); 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, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, R>); assert((): true => true as TEq>, 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, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, R>); assert((): true => true as TEq>, R>); assert((): true => true as TEq, Required

>); }); }); describe('Immutable', () => { it('', () => { type I = { readonly a?: [number]; readonly b: { c: string; }; readonly d: () => 0; readonly e: new () => object, f: Set, g: ReadonlySet }; type M = { a?: [number]; b: { c: string; }; d: () => 0; e: new () => object, f: Set, g: ReadonlySet }; assert((): true => true as TEq, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, I>); assert((): true => true as TEq, ReadonlyArray>); assert((): true => true as TEq, { 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, g: ReadonlySet }; }; type M = { a?: number; b: { c: [string]; d: () => 0; e: new () => object, f: Set, g: ReadonlySet }; }; assert((): true => true as TEq, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, I>); assert((): true => true as TEq, Immutable>); assert((): true => true as TEq, ReadonlyArray>); assert((): true => true as TEq, { 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, g: ReadonlySet }; type M = { a?: [number]; b: { c: string; }; d: () => 0; e: new () => object, f: Set, g: ReadonlySet }; assert((): true => true as TEq, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, M>); assert((): true => true as TEq, unknown[]>); assert((): true => true as TEq, { 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, g: ReadonlySet }; }; type M = { a?: number; b: { c: [string]; d: () => 0; e: new () => object, f: Set, g: Set }; }; assert((): true => true as TEq, never>); assert((): true => true as TEq, any>); assert((): true => true as TEq, unknown>); assert((): true => true as TEq, M>); assert((): true => true as TEq, Mutable>); assert((): true => true as TEq, unknown[]>); assert((): true => true as TEq, { 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', [])); }); }); });