Skip to content

Commit

Permalink
feat(types): Remap
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Jul 17, 2023
1 parent ec69978 commit fdf04f0
Show file tree
Hide file tree
Showing 13 changed files with 377 additions and 221 deletions.
42 changes: 12 additions & 30 deletions src/types/__tests__/at.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ describe('unit-d:types/At', () => {
expectTypeOf<TestSubject<never, 0, F>>().toEqualTypeOf<F>()
})

describe('T extends NIL', () => {
it('should equal F', () => {
// Arrange
type K = 0
type F = EmptyString

// Expect
expectTypeOf<TestSubject<null, K, F>>().toEqualTypeOf<F>()
expectTypeOf<TestSubject<undefined, K, F>>().toEqualTypeOf<F>()
})
})

describe('T extends readonly unknown[]', () => {
describe('IsTuple<T> extends true', () => {
it('should equal F if K is never', () => {
expectTypeOf<TestSubject<['a'], never, F>>().toEqualTypeOf<F>()
})

it('should equal Fallback<T[K], F> if Has<T, K> extends true', () => {
// Arrange
type T = { '3': number | undefined } & [Vehicle]
type K = '3' | 3
type Expect = Fallback<T[K], F>

// Expect
expectTypeOf<TestSubject<T, K, F>>().toEqualTypeOf<Expect>()
})

it('should equal Fallback<T[number], F> if K is any', () => {
// Arrange
type T = ['a', 'b', 'c'?]
Expand Down Expand Up @@ -158,16 +160,6 @@ describe('unit-d:types/At', () => {
expectTypeOf<TestSubject<T, Integer, F>>().toEqualTypeOf<Expect>()
expectTypeOf<TestSubject<T, any, F>>().toEqualTypeOf<Expect>()
})

it('should equal Fallback<T[K], F> if Has<T, K> extends true', () => {
// Arrange
type T = Vehicle[] & { '3': number | undefined }
type K = '3' | 3
type Expect = Fallback<T[K], F>

// Expect
expectTypeOf<TestSubject<T, K, F>>().toEqualTypeOf<Expect>()
})
})
})

Expand Down Expand Up @@ -294,16 +286,6 @@ describe('unit-d:types/At', () => {
expectTypeOf<TestSubject<T, Integer, F>>().toEqualTypeOf<Expect>()
expectTypeOf<TestSubject<T, any, F>>().toEqualTypeOf<Expect>()
})

it('should equal Fallback<T[K], F> if Has<T, K> extends true', () => {
// Arrange
type T = string & { '3': number | undefined }
type K = '3' | 3
type Expect = Fallback<T[K], F>

// Expect
expectTypeOf<TestSubject<T, K, F>>().toEqualTypeOf<Expect>()
})
})
})

Expand Down
9 changes: 9 additions & 0 deletions src/types/__tests__/invert.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,13 @@ describe('unit-d:types/Invert', () => {
})
})
})

describe('T extends NIL', () => {
type Expect = Record<never, never>

it('should equal Record<never, never>', () => {
expectTypeOf<TestSubject<null>>().toEqualTypeOf<Expect>()
expectTypeOf<TestSubject<undefined>>().toEqualTypeOf<Expect>()
})
})
})
7 changes: 3 additions & 4 deletions src/types/__tests__/keyof.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type EmptyObject from '../empty-object'
import type Fn from '../fn'
import type Indices from '../indices'
import type TestSubject from '../keyof'
import type NIL from '../nil'
import type Nilable from '../nilable'
import type NumberLike from '../number-like'
import type { tag } from '../opaque'
Expand Down Expand Up @@ -41,7 +40,8 @@ describe('unit-d:types/Keyof', () => {
expectTypeOf<TestSubject<T2>>().toEqualTypeOf<keyof T2>()
})

it('should equal never if typeof EmptyObjectTag extends keyof T', () => {
it('should equal never if EmptyObjectTag extends T', () => {
expectTypeOf<TestSubject<{}>>().toBeNever()
expectTypeOf<TestSubject<EmptyObject>>().toBeNever()
})

Expand All @@ -56,8 +56,7 @@ describe('unit-d:types/Keyof', () => {
})

describe('T extends Primitive', () => {
it('should equal never if keyof T is never', () => {
expectTypeOf<TestSubject<NIL>>().toBeNever()
it('should equal never if IsNever<keyof Remap<T>> extends true', () => {
expectTypeOf<TestSubject<null>>().toBeNever()
expectTypeOf<TestSubject<undefined>>().toBeNever()
})
Expand Down
7 changes: 3 additions & 4 deletions src/types/__tests__/keys-optional-exact.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type EmptyObject from '../empty-object'
import type Fn from '../fn'
import type Indices from '../indices'
import type TestSubject from '../keys-optional-exact'
import type NIL from '../nil'
import type Optional from '../optional'

describe('unit-d:types/ExactOptionalKeys', () => {
Expand All @@ -36,14 +35,14 @@ describe('unit-d:types/ExactOptionalKeys', () => {
expectTypeOf<TestSubject<T2>>().toEqualTypeOf<keyof Vehicle>()
})

it('should equal never if Keyof<T> is never', () => {
it('should equal never if IsNever<keyof Objectify<T>> extends true', () => {
expectTypeOf<TestSubject<{}>>().toBeNever()
expectTypeOf<TestSubject<EmptyObject>>().toBeNever()
})
})

describe('T extends Primitive', () => {
it('should equal never if Keyof<T> is never', () => {
expectTypeOf<TestSubject<NIL>>().toBeNever()
it('should equal never if IsNever<keyof Objectify<T>> extends true', () => {
expectTypeOf<TestSubject<null>>().toBeNever()
expectTypeOf<TestSubject<undefined>>().toBeNever()
})
Expand Down
188 changes: 188 additions & 0 deletions src/types/__tests__/remap.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/**
* @file Type Tests - Remap
* @module tutils/types/tests/unit-d/Remap
*/

import type Vehicle from '#fixtures/vehicle'
import type At from '../at'
import type Fn from '../fn'
import type IfNumeric from '../if-numeric'
import type Nullable from '../nullable'
import type Objectify from '../objectify'
import type { tag } from '../opaque'
import type Partial from '../partial'
import type TestSubject from '../remap'

describe('unit-d:types/Remap', () => {
it('should equal Objectify<T> if T is any', () => {
// Arrange
type T = any

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})

it('should equal Objectify<T> if T is never', () => {
// Arrange
type T = never

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})

it('should equal Objectify<T> if T is unknown', () => {
// Arrange
type T = unknown

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})

describe('T extends ObjectCurly', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = Vehicle

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})

describe('T extends Primitive', () => {
describe('T extends NIL', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T1 = null
type T2 = undefined

// Expect
expectTypeOf<TestSubject<T1>>().toEqualTypeOf<Objectify<T1>>()
expectTypeOf<TestSubject<T2>>().toEqualTypeOf<Objectify<T2>>()
})
})

describe('T extends bigint', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = 1n

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})

describe('T extends boolean', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = false

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})

describe('T extends number', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = 1

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})

describe('T extends string', () => {
describe('IsLiteral<T> extends true', () => {
it('should construct object representation of T', () => {
// Arrange
type T = 'vin'

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<
{
[x: number]: At<T, number>
0: At<T, 0>
1: At<T, 1>
2: At<T, 2>
[-1]: At<T, -1>
[-2]: At<T, -2>
[-3]: At<T, -3>
} & { [K in keyof T as number extends K ? never : K]: T[K] }
>()
})
})

describe('number extends Indices<T>', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = string

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})
})

describe('T extends symbol', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = typeof tag

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})
})

describe('T extends Readonly<Fn>', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = Readonly<Fn>

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})

describe('T extends readonly unknown[]', () => {
describe('IsTuple<T> extends true', () => {
it('should construct object representation of T', () => {
// Arrange
type T = readonly [Vehicle, Vehicle, Nullable<Vehicle>?]

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<
{
readonly 0: At<T, 0>
readonly 1: At<T, 1>
readonly 2?: At<T, 2, never>
readonly [-1]?: At<T, -1, never>
readonly [-2]: At<T, -2>
readonly [-3]: At<T, -3>
} & { [K in keyof T as IfNumeric<K, never, K>]: T[K] }
>()
})
})

describe('number extends Indices<T>', () => {
it('should equal Objectify<T>', () => {
// Arrange
type T = Partial<(Vehicle | Vehicle['vin'])[]>

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Objectify<T>>()
})
})
})

describe('unions', () => {
it('should distribute over unions', () => {
// Arrange
type T = Nullable<Vehicle | Vehicle['vin']>
type Expect = Objectify<null> | Objectify<string> | Objectify<Vehicle>

// Expect
expectTypeOf<TestSubject<T>>().toEqualTypeOf<Expect>()
})
})
})
Loading

0 comments on commit fdf04f0

Please sign in to comment.