Skip to content

Commit

Permalink
feat(types): Times
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 5a19e38 commit 6116ec2
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/types/__tests__/subtract.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type TestSubject from '../subtract'

describe('unit-d:types/Subtract', () => {
it('should equal difference between M and S', () => {
expectTypeOf<TestSubject<5, 2>>().toEqualTypeOf<3>()
expectTypeOf<TestSubject<3, 3>>().toEqualTypeOf<0>()
expectTypeOf<TestSubject<100, 97>>().toEqualTypeOf<3>()
})
})
133 changes: 133 additions & 0 deletions src/types/__tests__/times.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* @file Type Tests - Times
* @module tutils/types/tests/unit-d/Times
*/

import type Vehicle from '#fixtures/vehicle'
import type EmptyArray from '../empty-array'
import type TestSubject from '../times'

describe('unit-d:types/Times', () => {
type V = Vehicle | Vehicle['vin'] | Vehicle['year']

it('should equal EmptyArray if L is never', () => {
expectTypeOf<TestSubject<never, V>>().toEqualTypeOf<EmptyArray>()
})

it('should equal V[] if L is any', () => {
expectTypeOf<TestSubject<any, V>>().toEqualTypeOf<V[]>()
})

describe('L extends number', () => {
it('should construct tuple of length L', () => {
expectTypeOf<TestSubject<100, V>>().toEqualTypeOf<
[
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V,
V
]
>()
})

it('should equal V[] if number extends L', () => {
expectTypeOf<TestSubject<number, V>>().toEqualTypeOf<V[]>()
})
})
})
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export type { default as Split } from './split'
export type { default as Stringafiable } from './stringafiable'
export type { default as Stringify } from './stringify'
export type { default as Tail } from './tail'
export type { default as Times } from './times'
export type { default as Timestamp } from './timestamp'
export type { default as TimestampFormat } from './timestamp-format'
export type { default as TimestampToken } from './timestamp-token'
Expand Down
34 changes: 4 additions & 30 deletions src/types/subtract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,7 @@
* @module tutils/types/Subtract
*/

import type EmptyArray from './empty-array'

/**
* Creates a tuple of length `L`.
*
* @internal
*
* @template L - Tuple size
* @template Acc - Tuple elements accumulator
*/
type BuildTuple<
L extends number,
Acc extends readonly unknown[] = EmptyArray
> = Acc extends { length: L } ? Acc : BuildTuple<L, [...Acc, unknown]>

/**
* Returns the difference between `M` and `S`.
*
* @internal
*
* @template M - Minuend
* @template S - Subtrahend
*/
type Calculate<M extends number, S extends number> = BuildTuple<M> extends [
...infer U,
...BuildTuple<S>
]
? U['length']
: never
import type Times from './times'

/**
* Returns the difference between `M` and `S`.
Expand All @@ -43,7 +15,9 @@ type Calculate<M extends number, S extends number> = BuildTuple<M> extends [
*/
type Subtract<M extends number, S extends number> = M extends number
? S extends number
? Calculate<M, S>
? Times<M> extends [...Times<S>, ...infer R]
? R['length']
: never
: never
: never

Expand Down
44 changes: 44 additions & 0 deletions src/types/times.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @file Type Definitions - Times
* @module tutils/types/Times
*/

import type EmptyArray from './empty-array'
import type IsNever from './is-never'

/**
* Construct a tuple of length `L`.
*
* @example
* type X = Times<5>
* // [unknown, unknown, unknown, unknown, unknown]
* @example
* type X = Times<5, number>
* // [number, number, number, number, number]
* @example
* type X = Times<number, number>
* // number[]
* @example
* type X = Times<any, number>
* // number[]
* @example
* type X = Times<never, number>
* // []
*
* @template L - Tuple length
* @template V - Tuple item type
* @template Acc - Tuple elements accumulator
*/
type Times<
L extends number,
V = unknown,
Acc extends readonly unknown[] = EmptyArray
> = IsNever<L> extends true
? EmptyArray
: number extends L
? V[]
: Acc extends { length: L }
? Acc
: Times<L, V, [...Acc, V]>

export type { Times as default }

0 comments on commit 6116ec2

Please sign in to comment.