diff --git a/src/types/__tests__/if-symbol-unique.spec-d.ts b/src/types/__tests__/if-symbol-unique.spec-d.ts new file mode 100644 index 00000000..51045aab --- /dev/null +++ b/src/types/__tests__/if-symbol-unique.spec-d.ts @@ -0,0 +1,40 @@ +/** + * @file Type Tests - IfUniqueSymbol + * @module tutils/types/tests/unit-d/IfUniqueSymbol + */ + +import type { tag as empty } from '../empty-object' +import type TestSubject from '../if-symbol-unique' +import type Nilable from '../nilable' +import type { tag as opaque } from '../opaque' + +describe('unit-d:types/IfUniqueSymbol', () => { + type F = 0 + type T = 1 + + it('should equal F if IsUniqueSymbol extends false', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal F if U is any', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal F if U is never', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal T if IsUniqueSymbol extends true', () => { + expectTypeOf>().toEqualTypeOf() + }) + + describe('unions', () => { + it('should distribute over unions', () => { + // Arrange + type U = Nilable + + // Expect + expectTypeOf>().toEqualTypeOf() + }) + }) +}) diff --git a/src/types/__tests__/is-symbol-unique.spec-d.ts b/src/types/__tests__/is-symbol-unique.spec-d.ts new file mode 100644 index 00000000..c5ab7182 --- /dev/null +++ b/src/types/__tests__/is-symbol-unique.spec-d.ts @@ -0,0 +1,42 @@ +/** + * @file Type Tests - IsUniqueSymbol + * @module tutils/types/tests/unit-d/IsUniqueSymbol + */ + +import type EmptyObject from '../empty-object' +import type Integer from '../integer' +import type TestSubject from '../is-symbol-unique' +import type { tag as opaque } from '../opaque' + +describe('unit-d:types/IsUniqueSymbol', () => { + it('should equal false if T does not extend symbol', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal false if T extends object', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal false if T is any', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal false if T is never', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal false if symbol extends T', () => { + expectTypeOf>().toEqualTypeOf() + }) + + it('should equal true if T is unique symbol', () => { + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + }) + + describe('unions', () => { + it('should distribute over unions', () => { + expectTypeOf>().toEqualTypeOf() + }) + }) +}) diff --git a/src/types/if-symbol-unique.ts b/src/types/if-symbol-unique.ts new file mode 100644 index 00000000..11af5888 --- /dev/null +++ b/src/types/if-symbol-unique.ts @@ -0,0 +1,43 @@ +/** + * @file Type Definitions - IfUniqueSymbol + * @module tutils/types/IfUniqueSymbol + */ + +import type IfNever from './if-never' +import type IsUniqueSymbol from './is-symbol-unique' + +/** + * Returns a type that indicates if `U` is a type of `unique symbol`. + * + * @see {@linkcode IsUniqueSymbol} + * + * @example + * type X = IfUniqueSymbol + * // 1 + * @example + * type X = IfUniqueSymbol + * // 0 | 1 + * @example + * type X = IfUniqueSymbol + * // 0 + * @example + * type X = IfUniqueSymbol + * // 0 + * @example + * type X = IfUniqueSymbol + * // 0 + * @example + * type X = IfUniqueSymbol + * // 0 + * + * @template U - Type to evaluate + * @template T - Type if `U` is `unique symbol` + * @template F - Type if `U` is not a `unique symbol` + */ +type IfUniqueSymbol = IfNever< + U, + F, + U extends unknown ? (IsUniqueSymbol extends true ? T : F) : F +> + +export type { IfUniqueSymbol as default } diff --git a/src/types/index.ts b/src/types/index.ts index 605d24c4..8788ea98 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -68,6 +68,7 @@ export type { default as IfObjectPlain } from './if-object-plain' export type { default as IfPrimitive } from './if-primitive' export type { default as IfString } from './if-string' export type { default as IfSymbol } from './if-symbol' +export type { default as IfUniqueSymbol } from './if-symbol-unique' export type { default as IfTrue } from './if-true' export type { default as IfTuple } from './if-tuple' export type { default as IfUndefined } from './if-undefined' @@ -106,6 +107,7 @@ export type { default as IsObjectPlain } from './is-object-plain' export type { default as IsPrimitive } from './is-primitive' export type { default as IsString } from './is-string' export type { default as IsSymbol } from './is-symbol' +export type { default as IsUniqueSymbol } from './is-symbol-unique' export type { default as IsTrue } from './is-true' export type { default as IsTuple } from './is-tuple' export type { default as IsUndefined } from './is-undefined' diff --git a/src/types/is-symbol-unique.ts b/src/types/is-symbol-unique.ts new file mode 100644 index 00000000..7bc395c1 --- /dev/null +++ b/src/types/is-symbol-unique.ts @@ -0,0 +1,44 @@ +/** + * @file Type Definitions - IsUniqueSymbol + * @module tutils/types/IsUniqueSymbol + */ + +import type IfAnyOrNever from './if-any-or-never' + +/** + * Returns a boolean indicating if `T` is a type of `unique symbol`. + * + * @example + * type X = IsSymbol + * // true + * @example + * type X = IsSymbol + * // boolean + * @example + * type X = IsSymbol + * // false + * @example + * type X = IsSymbol + * // false + * @example + * type X = IsSymbol + * // false + * @example + * type X = IsSymbol + * // false + * + * @template T - Type to evaluate + */ +type IsUniqueSymbol = IfAnyOrNever< + T, + false, + T extends symbol + ? symbol extends T + ? false + : T extends object + ? false + : true + : false +> + +export type { IsUniqueSymbol as default }