Skip to content

Commit

Permalink
feat(types): Float, Integer
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed May 15, 2023
1 parent e7da94f commit 3632179
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 11 deletions.
17 changes: 17 additions & 0 deletions src/types/__tests__/float.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @file Type Tests - Float
* @module tutils/types/tests/unit-d/Float
*/

import type TestSubject from '../float'
import type { tag } from '../opaque'

describe('unit-d:types/Float', () => {
it('should extend number', () => {
expectTypeOf<TestSubject>().toMatchTypeOf<number>()
})

it('should match [readonly [tag]: "float"]', () => {
expectTypeOf<TestSubject>().toMatchTypeOf<{ readonly [tag]: 'float' }>()
})
})
17 changes: 17 additions & 0 deletions src/types/__tests__/integer.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @file Type Tests - Integer
* @module tutils/types/tests/unit-d/Integer
*/

import type TestSubject from '../integer'
import type { tag } from '../opaque'

describe('unit-d:types/Integer', () => {
it('should extend number', () => {
expectTypeOf<TestSubject>().toMatchTypeOf<number>()
})

it('should match [readonly [tag]: "integer"]', () => {
expectTypeOf<TestSubject>().toMatchTypeOf<{ readonly [tag]: 'integer' }>()
})
})
11 changes: 4 additions & 7 deletions src/types/__tests__/opaque.spec-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,17 @@
*/

import type TestSubject from '../opaque'
import type { tag } from '../opaque'

describe('unit-d:types/Opaque', () => {
type B = number
type T = 'account-number'

it('should be assignable to type of B', () => {
it('should extend B', () => {
expectTypeOf<TestSubject<B, T>>().toMatchTypeOf<B>()
})

it('should not match opaque type with same base and different token', () => {
// Arrange
type T2 = 'account-balance'

// Expect
expectTypeOf<TestSubject<B, T>>().not.toMatchTypeOf<TestSubject<B, T2>>()
it('should match [readonly [tag]: T]', () => {
expectTypeOf<TestSubject<B, T>>().toMatchTypeOf<{ readonly [tag]: T }>()
})
})
15 changes: 15 additions & 0 deletions src/types/float.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @file Type Definitions - Float
* @module tutils/types/Float
*/

import type Opaque from './opaque'

/**
* A floating point number.
*
* @see https://computersciencewiki.org/index.php/float
*/
type Float = Opaque<number, 'float'>

export type { Float as default }
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type { default as EnsureString } from './ensure-string'
export type { default as ExactOptionalPropertyTypes } from './exact-optional-property-types'
export type { default as Fallback } from './fallback'
export type { default as FIXME } from './fixme'
export type { default as Float } from './float'
export type { default as Fn } from './fn'
export type { default as Get } from './get'
export type { default as IfAny } from './if-any'
Expand All @@ -40,6 +41,7 @@ export type { default as IfUndefined } from './if-undefined'
export type { default as IfUnknown } from './if-unknown'
export type { default as IndexSignature } from './index-signature'
export type { default as Indices } from './indices'
export type { default as Integer } from './integer'
export type { default as IsAny } from './is-any'
export type { default as IsArray } from './is-array'
export type { default as IsBigInt } from './is-big-int'
Expand Down
16 changes: 16 additions & 0 deletions src/types/integer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @file Type Definitions - Integer
* @module tutils/types/Integer
*/

import type Opaque from './opaque'

/**
* A number that can be negative, positive, or zero, but not a fraction (i.e.
* cannot have a decimal point).
*
* @see https://computersciencewiki.org/index.php/int
*/
type Integer = Opaque<number, 'integer'>

export type { Integer as default }
12 changes: 8 additions & 4 deletions src/types/opaque.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
*/

/**
* Token symbol for {@linkcode Opaque}.
* {@linkcode Opaque} type token key.
*/
declare const token: unique symbol
export declare const tag: unique symbol

/**
* Creates an [opaque type][1].
Expand All @@ -17,11 +17,15 @@ declare const token: unique symbol
* The type token parameter, `T`, allows TypeScript to differentiate between
* opaque types with the same base type.
*
* [1]: https://codemix.com/opaque-types-in-javascript/
* [1]: https://codemix.com/opaque-types-in-javascript
*
* @see https://github.com/Microsoft/TypeScript/issues/202
* @see https://github.com/Microsoft/TypeScript/issues/15408
* @see https://github.com/Microsoft/TypeScript/issues/15807
*
* @template B - Base type
* @template T - Type token
*/
type Opaque<B, T = unknown> = B & { readonly [token]: T }
type Opaque<B, T = unknown> = B & { readonly [tag]: T }

export type { Opaque as default }

0 comments on commit 3632179

Please sign in to comment.