JSPM

@avstantso/ts

1.2.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 975
  • Score
    100M100P100Q75817F
  • License MIT

TypeScript helpers

Package Exports

  • @avstantso/ts
  • @avstantso/ts/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@avstantso/ts) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@avstantso/ts

npm version License: MIT

Advanced TypeScript type system utilities and helpers for creating powerful generic types, performing type-level computations, and building type-safe applications.

Features

  • Type-level arithmetic - Increment, decrement, addition, subtraction, multiplication, division, and power operations on numeric literals
  • Advanced array types - Create, manipulate, sort, filter, and transform array types with utilities like Create, Sort, FilterUnique, Reverse, Join
  • String manipulation types - String length, case conversions (camelCase, PascalCase, snake_case, kebab-case), trimming, replacement, and pattern matching
  • Union utilities - Convert unions to intersections, tuples, test for union types, and more
  • Structure (object) utilities - Deep type manipulation, key/value extraction, flattening, reversing, splitting, and combining
  • Comparison types - Type-level <, <=, >, >= comparisons for both numbers and strings based on ASCII codes
  • ASCII character types - Complete ASCII character maps, character code lookups, and letter arrays
  • Type resolution system - Resolve literal type names to their actual types with extensible literal registration
  • Utility types - Alternative fields (Alt), opaque types, type merging, key replacement, and conditional type selection
  • Comprehensive type system with zero runtime dependencies

Installation

npm install @avstantso/ts

or

yarn add @avstantso/ts

Usage

Global Access

Import the package to register the AVStantso.TS namespace globally:

import '@avstantso/ts';

// Use types from the global namespace
type Incremented = AVStantso.TS.Increment<5>; // 6
type Sorted = AVStantso.TS.Array.Sort<[3, 1, 2]>; // [1, 2, 3]
type CamelCase = AVStantso.TS.String.Case.Camel<'hello-world'>; // 'helloWorld'

Direct Member Imports

Import the TS namespace directly for cleaner code:

import { TS } from '@avstantso/ts';

// Use imported TS namespace
type Incremented = TS.Increment<5>; // 6
type Sorted = TS.Array.Sort<[3, 1, 2]>; // [1, 2, 3]
type CamelCase = TS.String.Case.Camel<'hello-world'>; // 'helloWorld'

// Runtime utilities are also available
const field = TS.Array.ToKey2Key(['id', 'name', 'email'] as const);
console.log(field.id); // 'id'

const flattened = TS.flat({ a: 1, b: { c: 2 } }); // { a: 1, c: 2 }

Exported Members:

  • TS - Complete TypeScript utilities namespace (same as AVStantso.TS)

API Reference

Type System Overview

The @avstantso/ts package provides a comprehensive suite of type-level utilities organized into the following namespaces:


TS.Extends

Type extension checking with support for undefined === undefined.

TS.Extends<T1, T2, IfTrue = true, IfFalse = false>

Check if T1 extends T2.

Type Parameters:

  • T1 - The type to check
  • T2 - The type to check against
  • IfTrue - Return value if T1 extends T2 (default: true)
  • IfFalse - Return value if T1 does not extend T2 (default: false)

Example:

import { TS } from '@avstantso/ts';

type IsString = TS.Extends<string, string>; // true
type IsNumber = TS.Extends<number, string>; // false
type WithCustom = TS.Extends<string, string, 'yes', 'no'>; // 'yes'

TS.Increment / TS.Decrement

The cornerstone of many recursive type operations. Used for type-level iterations.

⛔ Inc/Dec Limitation

Current implementation has a limit of 999 iterations. Operations are defined on the Numeric.Domain.Positive range.

TS.Increment<N>

Increment numeric literal inside Numeric.Domain.Positive.

Type Parameters:

  • N - Numeric literal to increment (must be in range [0, 999])

Returns: N + 1 or number if out of range

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Increment<0>; // 1
type One = TS.Increment<1>; // 2
type Max = TS.Increment<255>; // 256

type Never = TS.Increment<never>; // number

TS.Decrement<N>

Decrement numeric literal inside Numeric.Domain.Positive.

Type Parameters:

  • N - Numeric literal to decrement (must be in range [0, 999])

Returns: N - 1 or number if out of range

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Decrement<0>; // -1
type One = TS.Decrement<1>; // 0
type Large = TS.Decrement<255>; // 254

type Never = TS.Decrement<never>; // number

TS.ArrN and TS.ArrM

TS.ArrN

readonly [any?, ... 996 more ...?, any?] - Array type constraint for Increment/Decrement-dependent types.

TS.ArrM<T = any, N extends number = 2>

Array of N items or more.

Type Parameters:

  • T - Element type (default: any)
  • N - Minimum number of elements (default: 2)

Example:

import { TS } from '@avstantso/ts';

type AtLeastTwo = TS.ArrM<string, 2>; // [string, string, ...string[]]
type AtLeastThree = TS.ArrM<number, 3>; // [number, number, number, ...number[]]

TS.Func

Extends function types defined in the @avstantso/core package.

TS.Func.Nested<Depth, R, P>

Nested function generic type.

Type Parameters:

  • Depth - Nesting depth
  • R - Return type of the innermost function
  • P - Parameter types (optional)

Example:

import { TS } from '@avstantso/ts';

type TripleNested = TS.Func.Nested<3, number>;
// Equivalent to: () => () => () => number

const fn: TripleNested = () => () => () => 42;

TS.Union

Union type utilities based on microsoft/TypeScript#13298 and Shannon Jackson's implementation.

TS.Union.ToIntersection<U>

Convert a union to an intersection: X | Y | ZX & Y & Z.

Example:

import { TS } from '@avstantso/ts';

type Union = { a: number } | { b: string };
type Intersection = TS.Union.ToIntersection<Union>; // { a: number } & { b: string }

TS.Union.Pop<U>

Takes last item from union: X | Y | ZZ.

Warning: May not always take the actual last item due to union ordering.

TS.Union.ToTuple<U>

Convert union to tuple: X | Y | Z[X, Y, Z].

Warning: Order of items is not guaranteed.

Example:

import { TS } from '@avstantso/ts';

type Union = 'a' | 'b' | 'c';
type Tuple = TS.Union.ToTuple<Union>; // ['a', 'b', 'c'] (order may vary)

TS.Union.IsUnion<T, IfTrue = true, IfFalse = false>

Test if type is a union.

Example:

import { TS } from '@avstantso/ts';

type MyUnion = 'a' | 'b' | 'c';
type NotUnion = string;

type Check1 = TS.Union.IsUnion<MyUnion>; // true
type Check2 = TS.Union.IsUnion<NotUnion>; // false
type Check3 = TS.Union.IsUnion<never>; // false
type Check4 = TS.Union.IsUnion<number | boolean>; // true

TS.Array

Comprehensive array type utilities for creation, manipulation, searching, and transformation.

Array Creation Types

TS.Array.Create<L, Item>

Creates array of Item with specified length L. ⛔Inc/Dec

Example:

import { TS } from '@avstantso/ts';

type FiveThrees = TS.Array.Create<5, 3>; // [3, 3, 3, 3, 3]

TS.Array.Create.Optional<L, Item>

Creates optional array of Item with specified length L. ⛔Inc/Dec

Example:

import { TS } from '@avstantso/ts';

type FiveOptional = TS.Array.Create.Optional<5, 3>; // [3?, 3?, 3?, 3?, 3?]

TS.Array.Numbers<L>

Creates numeric literals array from 0 to L-1. ⛔Inc/Dec

Example:

import { TS } from '@avstantso/ts';

type FirstThree = TS.Array.Numbers<3>; // [0, 1, 2]

TS.Array.Letters<L>

Creates letters literals array with length L. ⛔Inc/Dec

Example:

import { TS } from '@avstantso/ts';

type ABC = TS.Array.Letters<3>; // ['A', 'B', 'C']

Array Analysis Types

TS.Array.Length<TArr>

Get array type length.

Example:

import { TS } from '@avstantso/ts';

type Len = TS.Array.Length<[1, 5, 7]>; // 3
TS.Array.Length.IfExeeded<TArr, N, IfTrue = true, IfFalse = false>

Test if array type length exceeds N.

Example:

import { TS } from '@avstantso/ts';

type Exceeded = TS.Array.Length.IfExeeded<[1, 5, 7], 2>; // true
type NotExceeded = TS.Array.Length.IfExeeded<[1, 5, 7], 3>; // false

Array Search Types

TS.Array.IndexOf<TArr, Item, I = 0>

Find index of type in array type.

Example:

import { TS } from '@avstantso/ts';

type Idx = TS.Array.IndexOf<[undefined, undefined, 'x'], 'x'>; // 2

TS.Array.IfHasItem<TArr, Item, IfTrue = true, IfFalse = false>

Test if array type has item.

Example:

import { TS } from '@avstantso/ts';

type Has = TS.Array.IfHasItem<[1, undefined, 3, 4], 4>; // true

TS.Array.IfEach<TArr, Item, IfTrue = true, IfFalse = false>

Test if each item in array type extends Item.

Example:

import { TS } from '@avstantso/ts';

type AllUndefined = TS.Array.IfEach<[undefined, undefined, undefined], undefined>; // true
type NotAll = TS.Array.IfEach<[undefined, undefined, 3], undefined>; // false

TS.Array.CountOf<TArr, Item>

Calculate count of items that extend Item in array TArr.

Example:

import { TS } from '@avstantso/ts';

type Count1 = TS.Array.CountOf<[1, 2, 3], 3>; // 1
type Count3 = TS.Array.CountOf<[2, 2, 2], 2>; // 3

Array Transformation Types

TS.Array.AddUnique<TArr, Item>

Create array type with addition if item does not exist.

Example:

import { TS } from '@avstantso/ts';

type Added = TS.Array.AddUnique<[2, 3], 1>; // [2, 3, 1]
type NotAdded = TS.Array.AddUnique<[1, 2, 3], 1>; // [1, 2, 3]

TS.Array.MergeUnique<TArr1, TArr2>

Create merged array type from two arrays without duplicates from TArr2.

Example:

import { TS } from '@avstantso/ts';

type Merged = TS.Array.MergeUnique<[6, 1, 4], [1, 2, 3, 1, 4, 2, 5]>; // [6, 1, 4, 2, 3, 5]
type WithUndefined = TS.Array.MergeUnique<[6, 1, 4], [1, 2, undefined, 1, 4, 2, undefined]>;
// [6, 1, 4, 2, undefined]

TS.Array.FilterUnique<TArr>

Create array type from array without duplicates.

Example:

import { TS } from '@avstantso/ts';

type Unique = TS.Array.FilterUnique<[1, 2, 3, 1, 4, 2, 5]>; // [1, 2, 3, 4, 5]
type WithUndefined = TS.Array.FilterUnique<[1, 2, 3, undefined, 1, 4, undefined, 5]>;
// [1, 2, 3, undefined, 4, 5]

TS.Array.Sub<TArr, Start, End>

Create sub array type from Start to End (exclusive).

Example:

import { TS } from '@avstantso/ts';

type SubArray = TS.Array.Sub<[1, 2, 3, undefined, 5, 6], 2, 5>; // [3, undefined, 5]
type All = TS.Array.Sub<[1, 2, 3, 4, 5, 6], undefined, undefined>; // [1, 2, 3, 4, 5, 6]

TS.Array.Remove<TArr, Start, End>

Create new array type without removed section.

Example:

import { TS } from '@avstantso/ts';

type Removed = TS.Array.Remove<[1, 2, 3, 4, 5, 6], 2, 5>; // [1, 2, 6]
type Empty = TS.Array.Remove<[1, 2, 3, 4, 5, 6], undefined, undefined>; // []

TS.Array.Reverse<TArr>

Reverse array type.

Example:

import { TS } from '@avstantso/ts';

type Reversed = TS.Array.Reverse<[1, 2, 3]>; // [3, 2, 1]
type Mixed = TS.Array.Reverse<[1, undefined, 3, 'a']>; // ['a', 3, undefined, 1]

TS.Array.Join<TArr>

Join array type to string.

Example:

import { TS } from '@avstantso/ts';

type Joined = TS.Array.Join<[1, 2, 3]>; // '123'
type ReadonlyJoined = TS.Array.Join<readonly ['a', 1, true, 123456789012345]>;
// 'a1true123456789012345'

TS.Array.Cast<TArr, Item = any>

Cast all TArr items to Item type (items that don't match become never).

Example:

import { TS } from '@avstantso/ts';

type Same = TS.Array.Cast<[1, 2, 3]>; // [1, 2, 3]
type Numbers = TS.Array.Cast<[1, 2, 3], number>; // [1, 2, 3]
type Strings = TS.Array.Cast<[1, 2, 3], string>; // [never, never, never]
type Mixed = TS.Array.Cast<[1, undefined, 3], string>; // [never, undefined, never]

Array Map/Record Types

TS.Array.ToKey<TArr>

Calculate key union from array of keys (equivalent to TArr[number]).

Example:

import { TS } from '@avstantso/ts';

type Keys = TS.Array.ToKey<['a', 1]>; // 'a' | 1
type ReadonlyKeys = TS.Array.ToKey<readonly ['a', 1]>; // 'a' | 1

TS.Array.ToKey2Key<TArr>

Calculate key-to-key record from array of keys.

Example:

import { TS } from '@avstantso/ts';

type KeyMap = TS.Array.ToKey2Key<['a', 1]>; // { a: 'a', 1: 1 }

TS.Array.ToRecord<TArr, T>

Calculate record of type T with keys from array.

Example:

import { TS } from '@avstantso/ts';

type StringRecord = TS.Array.ToRecord<['a'], string>; // { a: string }
type BoolRecord = TS.Array.ToRecord<['a', 1], boolean>; // { a: boolean, 1: boolean }

TS.Array.KeyValueMapFrom<Keys, FirstValue = 0>

Create key-value map from list of keys and first value. Used in TS.ASCII.

Example:

import { TS } from '@avstantso/ts';

type Map1 = TS.Array.KeyValueMapFrom<['a', undefined, 1]>; // { a: 0; 1: 2 }
type Map2 = TS.Array.KeyValueMapFrom<['a', never, 1]>; // { a: 0; 1: 2 }

TS.Array.ValueKeyMapFrom<Keys, FirstValue = 0>

Create value-key map from list of keys and first value.

Example:

import { TS } from '@avstantso/ts';

type Map = TS.Array.ValueKeyMapFrom<['a', undefined, 1]>; // { 0: 'a'; 1: undefined; 2: 1 }

Array Min/Max/Sort Types

TS.Array.Min<TArr>

Find array minimal item.

Example:

import { TS } from '@avstantso/ts';

type MinNum = TS.Array.Min<[2, 1]>; // 1
type MinNumWithUndefined = TS.Array.Min<[2, undefined, 1]>; // 1
type MinStr = TS.Array.Min<['b', 'a']>; // 'a'
type MinStrWithUndefined = TS.Array.Min<['b', undefined, 'a']>; // 'a'
TS.Array.Min.Index<TArr>

Find array minimal item index.

Example:

import { TS } from '@avstantso/ts';

type Idx1 = TS.Array.Min.Index<[2, 1]>; // 1
type Idx2 = TS.Array.Min.Index<[1, 2]>; // 0
type IdxStr = TS.Array.Min.Index<['b', undefined, 'a']>; // 2

TS.Array.Max<TArr>

Find array maximal item.

Example:

import { TS } from '@avstantso/ts';

type MaxNum = TS.Array.Max<[2, 1]>; // 2
type MaxNumWithUndefined = TS.Array.Max<[2, undefined, 1]>; // 2
type MaxStr = TS.Array.Max<['b', 'a']>; // 'b'
TS.Array.Max.Index<TArr>

Find array maximal item index.

Example:

import { TS } from '@avstantso/ts';

type Idx1 = TS.Array.Max.Index<[1, 2]>; // 1
type Idx2 = TS.Array.Max.Index<[1, undefined, 2]>; // 2

TS.Array.Sort<TArr, Asc = true>

Sort array items. Allows sorting array of Sort.Pair<K> to sort any data by key. Based on TS.Comparisons.

Example:

import { TS } from '@avstantso/ts';

type Numbers = [1, 4, 5, 3, 2, 78, 1];
type Sorted = TS.Array.Sort<Numbers>; // [1, 1, 2, 3, 4, 5, 78]
type SortedDesc = TS.Array.Sort<Numbers, false>; // [78, 5, 4, 3, 2, 1, 1]

type Strings = ['abc', 'eb', '', '1', 'ab', ' '];
type SortedStr = TS.Array.Sort<Strings>; // ['', ' ', '1', 'ab', 'abc', 'eb']
type SortedStrDesc = TS.Array.Sort<Strings, false>; // ['eb', 'abc', 'ab', '1', ' ', '']

// Sort by key using pairs
type Pairs = [[1, 'one'], [3, 'three'], [2, 'two']];
type SortedPairs = TS.Array.Sort<Pairs>; // [[1, 'one'], [2, 'two'], [3, 'three']]
TS.Array.Sort.Pair<K>

Pair key-data for sorting any data by key. First element is the sort key, second is the data.

TS.Array.Sort.Desc<TArr>

Sort array items descending (equivalent to Sort<TArr, false>).

Array Runtime Utilities

TS.Array.ToKey2Key<A>(arr: A)

Create key-to-key record from array for convenient field comparisons.

Parameters:

  • arr - Readonly array of keys

Returns: Object with keys mapping to themselves

Example:

import { TS } from '@avstantso/ts';

const Fields = ['id', 'name', 'version'] as const;
const Field = TS.Array.ToKey2Key(Fields);

// Type-safe field comparisons
if (Field.id === field) {
  console.log('Is "id"');
}

if (Field.name === field) {
  console.log('Is "name"');
}

if (Field.version === field) {
  console.log('Is "version"');
}

TS.ASCII

ASCII character types and utilities based on ascii-code.com. Used in TS.Comparisons for string comparison operations.

ASCII Types

TS.ASCII.Letters<IsUpper = true>

English letters array generic by case.

Example:

import { TS } from '@avstantso/ts';

type Upper = TS.ASCII.Letters<true>; // Letters.Upper
type Lower = TS.ASCII.Letters<false>; // Letters.Lower

TS.ASCII.Letters.Upper

English uppercase letters array type: ['A', 'B', 'C', ..., 'Z'].

TS.ASCII.Letters.Lower

English lowercase letters array type: ['a', 'b', 'c', ..., 'z'].

TS.ASCII

Readonly array type of all ASCII characters (character codes 0-255).

TS.ASCII.Control

Readonly array type of ASCII control characters (character codes 0-31).

TS.ASCII.Printable

Readonly array type of ASCII printable characters (character codes 32-127).

TS.ASCII.Extended

Readonly array type of extended ASCII codes (character codes 128-255).

TS.ASCII.Map

ASCII character to code map for all characters.

TS.ASCII.Map.Control

ASCII character to code map for control characters (codes 0-31).

TS.ASCII.Map.Printable

ASCII character to code map for printable characters (codes 32-127).

TS.ASCII.Map.Extended

ASCII character to code map for extended ASCII codes (codes 128-255).

TS.ASCII.Code<S>

Get ASCII character code of string S. Returns never if S is not a single character.

Example:

import { TS } from '@avstantso/ts';

type CodeA = TS.ASCII.Code<'A'>; // 65
type CodeSpace = TS.ASCII.Code<' '>; // 32
type Invalid = TS.ASCII.Code<'AB'>; // never

TS.ASCII.Character

Union of all ASCII characters.

ASCII Runtime Utilities

TS.ASCII

Runtime array of all ASCII characters.

Example:

import { TS } from '@avstantso/ts';

console.log(TS.ASCII[65]); // 'A'
console.log(TS.ASCII.length); // 256

TS.Comparisons

Type-level number and string comparisons.

String comparison is based on TS.ASCII character-to-number conversion. Number comparison splits numbers into digit arrays, compares lengths, then iterates through digits from most to least significant.

Comparison Types

TS.Comparisons.LT<A, B, IfTrue = true, IfFalse = false>

Test if A < B.

Example:

import { TS } from '@avstantso/ts';

type NumLess = TS.Comparisons.LT<1, 2>; // true
type NumNotLess = TS.Comparisons.LT<2, 1>; // false
type StrLess = TS.Comparisons.LT<'a', 'b'>; // true

TS.Comparisons.LTE<A, B, IfTrue = true, IfFalse = false>

Test if A <= B.

Example:

import { TS } from '@avstantso/ts';

type NumLessEq = TS.Comparisons.LTE<1, 1>; // true
type StrLessEq = TS.Comparisons.LTE<'a', 'a'>; // true

TS.Comparisons.GT<A, B, IfTrue = true, IfFalse = false>

Test if A > B.

Example:

import { TS } from '@avstantso/ts';

type NumGreater = TS.Comparisons.GT<2, 1>; // true
type StrGreater = TS.Comparisons.GT<'b', 'a'>; // true

TS.Comparisons.GTE<A, B, IfTrue = true, IfFalse = false>

Test if A >= B.

Example:

import { TS } from '@avstantso/ts';

type NumGreaterEq = TS.Comparisons.GTE<2, 2>; // true
type StrGreaterEq = TS.Comparisons.GTE<'b', 'b'>; // true

TS.String

String type manipulation utilities.

Basic String Types

TS.String.Possible

Types that can be converted to string literal using template literals: string | number | bigint | boolean.

Example:

import { TS } from '@avstantso/ts';

type Valid = `${TS.String.Possible}`; // string
type InvalidSymbol = `${symbol}`; // Error: Type 'symbol' is not assignable

TS.String.Pattern

Regular expression pattern shortcuts.

export interface Pattern {
  '\\s': ' \r\n\t\f\v' // Whitespace characters
}

String Analysis Types

TS.String.Length<S>

Calculate string literal length.

Example:

import { TS } from '@avstantso/ts';

type Len0 = TS.String.Length<''>; // 0
type Len1 = TS.String.Length<'A'>; // 1
type Len2 = TS.String.Length<'AB'>; // 2

TS.String.IsLengthBetween<S, Min, Max = Min, IfTrue = true, IfFalse = false>

Test if string literal length is in range [Min, Max].

Example:

import { TS } from '@avstantso/ts';

type Valid0 = TS.String.IsLengthBetween<'', 0>; // true
type Invalid0 = TS.String.IsLengthBetween<'', 1>; // false
type ValidRange = TS.String.IsLengthBetween<'A', 1, 2>; // true

TS.String.SplitToChars<S>

Split string literal into array of characters.

Example:

import { TS } from '@avstantso/ts';

type Empty = TS.String.SplitToChars<''>; // []
type Single = TS.String.SplitToChars<'A'>; // ['A']
type Multiple = TS.String.SplitToChars<'AB'>; // ['A', 'B']

String Manipulation Types

TS.String.Repeat<S, N>

Repeat string S by N times. ⛔Inc/Dec

Example:

import { TS } from '@avstantso/ts';

type Empty = TS.String.Repeat<'AB', 0>; // ''
type Triple = TS.String.Repeat<'A1', 3>; // 'A1A1A1'

TS.String.Includes<S, P, IfTrue = true, IfFalse = false>

Test if string S includes pattern P.

Example:

import { TS } from '@avstantso/ts';

type EmptyInEmpty = TS.String.Includes<'', ''>; // true
type EmptyInString = TS.String.Includes<'AB', ''>; // true
type CharInString = TS.String.Includes<'AB', 'A'>; // true
type FullMatch = TS.String.Includes<'AB', 'AB'>; // true

type Number = TS.String.Includes<'A8B', 8>; // true
type Boolean = TS.String.Includes<'AfalseB', false>; // true

type NotFound = TS.String.Includes<'AB', 'C'>; // false

TS.String.IndexOf<S, P>

Find index of pattern P in string S. Returns -1 if not found. Returns sorted array of pairs for union P.

Example:

import { TS } from '@avstantso/ts';

type Invalid1 = TS.String.IndexOf<'', ''>; // never
type Invalid2 = TS.String.IndexOf<'AB', ''>; // never
type FirstChar = TS.String.IndexOf<'AB', 'A'>; // 0
type SecondChar = TS.String.IndexOf<'AB', 'B'>; // 1
type Full = TS.String.IndexOf<'AB', 'AB'>; // 0

type NumIdx = TS.String.IndexOf<'A8B', 8>; // 1
type BoolIdx = TS.String.IndexOf<'AfalseB', false>; // 1

type NotFound = TS.String.IndexOf<'AB', 'C'>; // -1

// Union returns sorted pairs [index, match]
type Multiple = TS.String.IndexOf<'AfalseB', 'B' | false | 'l'>;
// [[1, false], [3, 'l'], [6, 'B']]

TS.String.Replace<S, M, T, N = 9999>

Replace in string S all substrings matching M with T, up to N times. M can be a union.

Example:

import { TS } from '@avstantso/ts';

type RemoveChars = TS.String.Replace<TS.String.Replace<'a-b_c_d', '_'>, '-'>; // 'abcd'
type Limited = TS.String.Replace<'123456_246', '2' | '4' | '6', '#', 3>; // '1#3#5#_246'
type Multiple = TS.String.Replace<'abcde', 'a' | 'b' | 'c' | 'd' | 'e', 'x '>;
// 'x x x x x '

TS.String.Trim<S>

Remove whitespace characters from start and end of string S.

Example:

import { TS } from '@avstantso/ts';

type NoTrim = TS.String.Trim<'abcd'>; // 'abcd'
type Trimmed = TS.String.Trim<' \r\n\t\f\v \r\n\t\f\v123456 \r\n\t\f\v \r\n\t\f\v'>;
// '123456'
TS.String.Trim.Start<S>

Remove whitespace characters from start of string S.

Example:

import { TS } from '@avstantso/ts';

type TrimStart = TS.String.Trim.Start<' \r\n\t\f\v123456 \r\n\t\f\v'>;
// '123456 \r\n\t\f\v'
TS.String.Trim.End<S>

Remove whitespace characters from end of string S.

Example:

import { TS } from '@avstantso/ts';

type TrimEnd = TS.String.Trim.End<' \r\n\t\f\v123456 \r\n\t\f\v'>;
// ' \r\n\t\f\v123456'

String Case Types

TS.String.Case<Type, S, R = Removes>

Convert string S to specified case format.

Case Types:

  • 'c' - camelCase
  • 'p' - PascalCase
  • 's' - snake_case
  • 'S' - SNAKE_UPPER_CASE
  • 'k' - kebab-case

Example:

import { TS } from '@avstantso/ts';

type Phrase = 'Oh! Jingle bells, jingle bells Jingle all the way';

type Camel = TS.String.Case<'c', Phrase>; // 'ohJingleBellsJingleBellsJingleAllTheWay'
type Pascal = TS.String.Case<'p', Phrase>; // 'OhJingleBellsJingleBellsJingleAllTheWay'
type Snake = TS.String.Case<'s', Phrase>; // 'oh_jingle_bells_jingle_bells_jingle_all_the_way'
type SnakeUp = TS.String.Case<'S', Phrase>; // 'OH_JINGLE_BELLS_JINGLE_BELLS_JINGLE_ALL_THE_WAY'
type Kebab = TS.String.Case<'k', Phrase>; // 'oh-jingle-bells-jingle-bells-jingle-all-the-way'
TS.String.Case.Settings.Removes

Characters to remove during case conversion: ' ' | '-' | '_' | ',' | '.' | '!'.

TS.String.Case.Settings.Removes.Map

Map of characters to remove (values ignored, only keys matter).

export interface AVStantso.TS.String.Case.Settings.Removes.Map {
  ' ': 0;
  '-': 0;
  '_': 0;
  ',': 0;
  '.': 0;
  '!': 0;
}

You can extend this interface for custom character removal.

TS.String.Case.Camel<S, R = Removes>

Convert to camelCase.

TS.String.Case.Pascal<S, R = Removes>

Convert to PascalCase.

TS.String.Case.Snake<S, R = Removes>

Convert to snake_case.

TS.String.Case.Snake.Up<S, R = Removes>

Convert to SNAKE_UPPER_CASE.

TS.String.Case.Kebab<S, R = Removes>

Convert to kebab-case.


TS.Structure

Utilities for object types with fields (excludes special types like Array, Map, Set).

Structure Test Types

TS.Structure.IfStructure<T, IfTrue = true, IfFalse = false>

Test if T is a structure object (not a special object type).

Example:

import { TS } from '@avstantso/ts';

type Number = TS.Structure.IfStructure<number>; // false
type String = TS.Structure.IfStructure<string>; // false
type Object = TS.Structure.IfStructure<{}>; // true
type ObjectType = TS.Structure.IfStructure<object>; // true
type Array = TS.Structure.IfStructure<[]>; // false
type Date = TS.Structure.IfStructure<Date>; // false
type Buffer = TS.Structure.IfStructure<Buffer>; // false
type Map = TS.Structure.IfStructure<Map<unknown, unknown>>; // false
type Set = TS.Structure.IfStructure<Set<unknown>>; // false

type PlainFunc = TS.Structure.IfStructure<(x: number) => string>; // false
type FuncWithProps = TS.Structure.IfStructure<((x: number) => string) & { y: 15 }>; // true

TS.Structure<T>

Constraint that T is a structure object.

TS.Structure.Wildcard

Non-strict structure type (any object structure).

TS.Structure.MapOfNotRules

Used as rules source in IfStructure. If a type extends one of these values, it's not a structure.

export interface MapOfNotRules extends AtomicObjects {
  Array: ReadonlyArray<unknown>;
  Map: ReadonlyMap<unknown, unknown>;
  Set: ReadonlySet<unknown>;
}
TS.Structure.NotRules

Rules for IfStructure (union of MapOfNotRules values).

Structure Conversion Types

TS.Structure.ToKeysArray<O>

Transform structure O to keys array. Based on TS.Union.ToTuple.

Example:

import { TS } from '@avstantso/ts';

type Keys1 = TS.Structure.ToKeysArray<{ a: 1, b: true }>; // ['a', 'b']
type Keys2 = TS.Structure.ToKeysArray<{ a: 1, b: true, c: () => null }>; // ['a', 'b', 'c']
type Invalid = TS.Structure.ToKeysArray<[]>; // never
TS.Structure.ToValuesArray<O>

Transform structure O to values array. Based on TS.Union.ToTuple.

Example:

import { TS } from '@avstantso/ts';

type Values1 = TS.Structure.ToValuesArray<{ a: 1, b: true }>; // [1, true]
type Values2 = TS.Structure.ToValuesArray<{ a: 1, b: true, c: () => null }>;
// [1, true, () => null]
type Invalid = TS.Structure.ToValuesArray<[]>; // never
TS.Structure.ToEntriesArray<O>

Transform structure O to entries array (key-value pairs). Based on TS.Union.ToTuple.

Example:

import { TS } from '@avstantso/ts';

type Entries1 = TS.Structure.ToEntriesArray<{ a: 1, b: true }>;
// [['a', 1], ['b', true]]

type Entries2 = TS.Structure.ToEntriesArray<{ a: 1, b: true, c: () => null }>;
// [['a', 1], ['b', true], ['c', () => null]]

type Invalid = TS.Structure.ToEntriesArray<[]>; // never

Structure Manipulation Types

TS.Structure.Separate<T>

Separate structure object T into plain and structural fields: [<Plain>, <Structural>].

Example:

import { TS } from '@avstantso/ts';

type Sep1 = TS.Structure.Separate<{
  a: number;
  b: { c: string };
  d: string;
  e: number[];
}>;
// [{
//   a: number;
//   d: string;
//   e: number[];
// }, {
//   b: { c: string };
// }]

type Sep2 = TS.Structure.Separate<{
  v: () => Buffer;
  w: (() => string) & { n: string };
}>;
// [{
//   v: () => Buffer;
// }, {
//   w: (() => string) & { n: string };
// }]
TS.Structure.Reverse<T, TProviderField = never>

Reverse structure object T to value-key map. Non-keyable values are ignored except objects with TProviderField.

Example:

import { TS } from '@avstantso/ts';

type Simple = TS.Structure.Reverse<{ x: 1; y: 'ABC'; z: { a: true } }>;
// { 1: 'x'; ABC: 'y' }

type WithProvider = TS.Structure.Reverse<{ x: 1; y: 'ABC'; z: { a: 15 } }, 'a'>;
// { 1: 'x'; ABC: 'y'; 15: 'z' }
TS.Structure.Split<O>

Split structural object O into array of single-field objects. Based on TS.Union.ToTuple.

Example:

import { TS } from '@avstantso/ts';

type Obj = {
  a: number;
  b: string;
  c: { x: bigint };
};

type Split = TS.Structure.Split<Obj>;
// [
//   { a: number },
//   { b: string },
//   { c: { x: bigint } }
// ]
TS.Structure.Combine<A>

Combine array A of structural object parts into single object.

Example:

import { TS } from '@avstantso/ts';

type Combined = TS.Structure.Combine<readonly [
  { a: number },
  { b: string },
  { c: { x: bigint } }
]>;
// {
//   a: number;
//   b: string;
//   c: { x: bigint };
// }

Structure Runtime Utilities

TS.Structure.is<T>(candidate, noSpecialClasses?): candidate is T

Check if candidate is a structure object and cast to T.

Parameters:

  • candidate - Value to test
  • noSpecialClasses - If true, returns false for Array, Map, Set, etc.

Example:

import { TS } from '@avstantso/ts';

const obj = { a: 1, b: 2 };
if (TS.Structure.is(obj)) {
  // obj is structure object
}

const arr = [1, 2, 3];
console.log(TS.Structure.is(arr)); // true (arrays are objects)
console.log(TS.Structure.is(arr, true)); // false (noSpecialClasses)
TS.Structure.keyByValue<T>(structure, value, field?)

Find structure object key by value or subvalue with field.

Parameters:

  • structure - Object to search in
  • value - Value to find
  • field - Optional field name for nested value lookup

Example:

import { TS } from '@avstantso/ts';

const config = { debug: 1, info: 2, error: 3 };
const key = TS.Structure.keyByValue(config, 2); // 'info'

const nested = { a: { id: 1 }, b: { id: 2 } };
const nestedKey = TS.Structure.keyByValue(nested, 2, 'id'); // 'b'
TS.Structure.reverse<T>(structure, field?)

Reverse structure object T to value-key map at runtime.

Parameters:

  • structure - Object to reverse
  • field - Optional field for extracting values from nested objects

Example:

import { TS } from '@avstantso/ts';

const config = { debug: 1, info: 2, error: 3 };
const reversed = TS.Structure.reverse(config);
// { 1: 'debug', 2: 'info', 3: 'error' }

Object Constructor Extensions

The package extends the Object constructor with typed versions of keys, values, and entries that preserve type information.

Object.keysEx<O>(o: O)

Returns typed array of enumerable string property names. Unlike Object.keys(), this preserves the exact key types.

Parameters:

  • o - Object to extract keys from

Returns: TS.Structure.ToKeysArray<O> - Typed array of keys

Example:

import '@avstantso/ts';

const obj = { id: 1, name: 'John', active: true } as const;

// Standard Object.keys - loses type information
const keys1 = Object.keys(obj); // string[]

// Object.keysEx - preserves exact key types
const keys2 = Object.keysEx(obj); // ['id', 'name', 'active']
// Type: ('id' | 'name' | 'active')[]

// Now you can use type-safe key access
keys2.forEach(key => {
  console.log(obj[key]); // TypeScript knows key is valid
});

Object.valuesEx<O>(o: O)

Returns typed array of enumerable property values. Unlike Object.values(), this preserves the exact value types.

Parameters:

  • o - Object to extract values from

Returns: TS.Structure.ToValuesArray<O> - Typed array of values

Example:

import '@avstantso/ts';

const obj = { id: 1, name: 'John', active: true } as const;

// Standard Object.values - loses type information
const values1 = Object.values(obj); // (string | number | boolean)[]

// Object.valuesEx - preserves exact value types
const values2 = Object.valuesEx(obj); // [1, 'John', true]
// Type: [1, 'John', true]

// Type information is preserved
const [id, name, active] = values2;
// id: 1, name: 'John', active: true

Object.entriesEx<O>(o: O)

Returns typed array of key-value pairs. Unlike Object.entries(), this preserves both key and value types.

Parameters:

  • o - Object to extract entries from

Returns: TS.Structure.ToEntriesArray<O> - Typed array of [key, value] pairs

Example:

import '@avstantso/ts';

const obj = { id: 1, name: 'John', active: true } as const;

// Standard Object.entries - loses type information
const entries1 = Object.entries(obj);
// [string, string | number | boolean][]

// Object.entriesEx - preserves exact key and value types
const entries2 = Object.entriesEx(obj);
// [['id', 1], ['name', 'John'], ['active', true]]
// Type: (['id', 1] | ['name', 'John'] | ['active', true])[]

// Type-safe iteration
entries2.forEach(([key, value]) => {
  // TypeScript knows the exact type of key and value for each entry
  console.log(`${key}: ${value}`);
});

// Type-safe destructuring
const [[idKey, idValue], [nameKey, nameValue], [activeKey, activeValue]] = entries2;
// idKey: 'id', idValue: 1
// nameKey: 'name', nameValue: 'John'
// activeKey: 'active', activeValue: true

Use Cases:

These typed extensions are particularly useful when:

  • Working with configuration objects where type safety matters
  • Iterating over object properties with type guarantees
  • Building type-safe mappers and transformers
  • Ensuring key-value correspondence in operations

Example - Type-Safe Object Mapper:

import '@avstantso/ts';

function mapObjectValues<T extends object, R>(
  obj: T,
  mapper: <K extends keyof T>(key: K, value: T[K]) => R
): Record<keyof T, R> {
  return Object.entriesEx(obj).reduce((acc, [key, value]) => {
    acc[key] = mapper(key, value);
    return acc;
  }, {} as Record<keyof T, R>);
}

const user = { id: 1, name: 'John', age: 30 } as const;

// Type-safe mapping with preserved keys
const stringified = mapObjectValues(user, (key, value) => {
  // key and value have exact types based on the object
  return `${key}: ${value}`;
});
// Result: { id: 'id: 1', name: 'name: John', age: 'age: 30' }

TS.Boolean

Boolean type utilities and logical operations.

TS.If<Condition, IfTrue = true, IfFalse = false>

Conditional type selection.

Example:

import { TS } from '@avstantso/ts';

type Yes = TS.If<true, 'yes', 'no'>; // 'yes'
type No = TS.If<false, 'yes', 'no'>; // 'no'

TS.If.And<Conditions, IfTrue = true, IfFalse = false>

Logical AND on array of conditions.

Example:

import { TS } from '@avstantso/ts';

type AllTrue = TS.If.And<[true, true, true]>; // true
type OneFalse = TS.If.And<[true, false, true]>; // false

TS.If.Or<Conditions, IfTrue = true, IfFalse = false>

Logical OR on array of conditions.

Example:

import { TS } from '@avstantso/ts';

type HasTrue = TS.If.Or<[false, true, false]>; // true
type AllFalse = TS.If.Or<[false, false, false]>; // false

TS.If.Xor<Conditions, IfTrue = true, IfFalse = false>

Logical XOR on array of conditions (true if exactly one condition is true).

Example:

import { TS } from '@avstantso/ts';

type OnlyOne = TS.If.Xor<[false, true, false]>; // true
type Multiple = TS.If.Xor<[true, true, false]>; // false
type None = TS.If.Xor<[false, false, false]>; // false

TS.Numeric

Numeric literal type utilities for type-level arithmetic and analysis.

Domain-Independent Types

TS.Numeric.IsPositive<N, IfTrue = true, IfFalse = false>

Test if number N is positive.

Example:

import { TS } from '@avstantso/ts';

type Positive = TS.Numeric.IsPositive<1>; // true
type Zero = TS.Numeric.IsPositive<0>; // false
type Negative = TS.Numeric.IsPositive<-1>; // false
type Never = TS.Numeric.IsPositive<never>; // never
type Undef = TS.Numeric.IsPositive<undefined>; // false

TS.Numeric.IsNegative<N, IfTrue = true, IfFalse = false>

Test if number N is negative.

Example:

import { TS } from '@avstantso/ts';

type Negative = TS.Numeric.IsNegative<-1>; // true
type Zero = TS.Numeric.IsNegative<0>; // false
type Positive = TS.Numeric.IsNegative<1>; // false

TS.Numeric.Positive.ToNegative<N>

Get negative of absolute value of numeric literal.

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Numeric.Positive.ToNegative<0>; // 0
type Neg1 = TS.Numeric.Positive.ToNegative<1>; // -1
type Neg255 = TS.Numeric.Positive.ToNegative<255>; // -255
type AlreadyNeg = TS.Numeric.Positive.ToNegative<-1>; // -1

TS.Numeric.Negative.ToPositive<N>

Get absolute value of negative numeric literal.

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Numeric.Negative.ToPositive<0>; // 0
type Pos1 = TS.Numeric.Negative.ToPositive<-1>; // 1
type Pos255 = TS.Numeric.Negative.ToPositive<-255>; // 255
type AlreadyPos = TS.Numeric.Negative.ToPositive<1>; // 1

TS.Numeric.Sign<N = any>

Get sign of number N: -1 | 0 | 1. Without parameter, returns the sign union type.

Example:

import { TS } from '@avstantso/ts';

type Pos = TS.Numeric.Sign<42>; // 1
type Neg = TS.Numeric.Sign<-42>; // -1
type Zero = TS.Numeric.Sign<0>; // 0
type SignUnion = TS.Numeric.Sign; // -1 | 0 | 1

TS.Numeric.Digits

Union of digit characters: keyof Digits.Map.

TS.Numeric.Digits.Map

Record of digit character to digit number: { '0': 0, '1': 1, ..., '9': 9 }.

TS.Numeric.Digits.IsOdd

Record of digit character to boolean indicating if odd: { '0': false, '1': true, ... }.

TS.Numeric.Digits.Hex

Union of hexadecimal digit characters: keyof Digits.Hex.Map.

Includes decimal digits (0-9) and hexadecimal letters (A-F).

Type Definition:

type Hex = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
TS.Numeric.Digits.Hex.Map

Record of hexadecimal digit character to itself, extending Digits.Map:

type Map = {
  '0': 0;
  '1': 1;
  '2': 2;
  '3': 3;
  '4': 4;
  '5': 5;
  '6': 6;
  '7': 7;
  '8': 8;
  '9': 9;
  'A': 'A';
  'B': 'B';
  'C': 'C';
  'D': 'D';
  'E': 'E';
  'F': 'F';
}

Example:

import { TS } from '@avstantso/ts';

// Use in type constraints
type HexDigit = TS.Numeric.Digits.Hex;
// '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'

// Validate hexadecimal strings
type IsHexChar<C extends string> = C extends HexDigit ? true : false;

type Valid1 = IsHexChar<'5'>; // true
type Valid2 = IsHexChar<'F'>; // true
type Invalid = IsHexChar<'G'>; // false

// Build hexadecimal string types
type HexByte = `${HexDigit}${HexDigit}`;
// '00' | '01' | ... | 'FF'

// ⚠ Watch out for TypeScript limits!
type ColorHex = `#${HexByte}${HexByte}${HexByte}`;
// '#000000' | '#000001' | ... | '#FFFFFF'

TS.Numeric.IsOdd<N, IfTrue = true, IfFalse = false>

Test if number is odd.

Example:

import { TS } from '@avstantso/ts';

type Odd = TS.Numeric.IsOdd<11>; // true
type Even = TS.Numeric.IsOdd<32>; // false

TS.Numeric.IsEven<N, IfTrue = true, IfFalse = false>

Test if number is even.

Example:

import { TS } from '@avstantso/ts';

type Even = TS.Numeric.IsEven<32>; // true
type Odd = TS.Numeric.IsEven<11>; // false

TS.Numeric.IsNumber<S, IfTrue = true, IfFalse = false>

Test if string S represents a number.

Example:

import { TS } from '@avstantso/ts';

type ValidPos = TS.Numeric.IsNumber<'1000'>; // true
type ValidNeg = TS.Numeric.IsNumber<'-1'>; // true
type Invalid = TS.Numeric.IsNumber<'abc'>; // false
type DoubleNeg = TS.Numeric.IsNumber<'--1'>; // false

TS.Numeric.Parse<S>

Parse string S to extract number from it.

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Numeric.Parse<'0'>; // 0
type Pos = TS.Numeric.Parse<'255'>; // 255
type Neg = TS.Numeric.Parse<'-255'>; // -255
type Invalid = TS.Numeric.Parse<'abc'>; // never
type Never = TS.Numeric.Parse<never>; // never
type Undef = TS.Numeric.Parse<undefined>; // undefined

Numeric Domain Types

Internal types for numeric operations. These define the range of numeric literals that can be manipulated.

TS.Numeric.Domain.Positive

Array of positive numbers: [1, 2, ..., 4999, ...number[]].

TS.Numeric.Domain.Negative

Array of negative numbers: [-1, -2, ..., -4999, ...number[]].

TS.Numeric.Domain.Increment<N>

Increment numeric literal within the full domain (including negative numbers).

Example:

import { TS } from '@avstantso/ts';

type Inc10 = TS.Numeric.Domain.Increment<10>; // 11
type Inc0 = TS.Numeric.Domain.Increment<0>; // 1
type IncNeg = TS.Numeric.Domain.Increment<-1>; // 0
type IncNeg10 = TS.Numeric.Domain.Increment<-10>; // -9

Note: This differs from TS.Increment which only works on 0 and positive numbers.

TS.Numeric.Domain.Decrement<N>

Decrement numeric literal within the full domain.

Example:

import { TS } from '@avstantso/ts';

type Dec10 = TS.Numeric.Domain.Decrement<10>; // 9
type Dec0 = TS.Numeric.Domain.Decrement<0>; // -1
type DecNeg = TS.Numeric.Domain.Decrement<-1>; // -2

Numeric Math Types

Type-level arithmetic operations. Developed as an exploration of TypeScript's type system capabilities.

TS.Numeric.Abs<N>

Absolute value of numeric literal (alias for Negative.ToPositive<N>).

TS.Numeric.Invert<N>

Invert sign of numeric literal (positive ⇔ negative).

Example:

import { TS } from '@avstantso/ts';

type Zero = TS.Numeric.Invert<0>; // 0
type ToNeg = TS.Numeric.Invert<1>; // -1
type ToPos = TS.Numeric.Invert<-255>; // 255

TS.Numeric.Summ<X, Y>

Calculate X + Y. Uses an optimized algorithm to avoid the 999 iteration limit.

Example:

import { TS } from '@avstantso/ts';

type Simple = TS.Numeric.Summ<8, 3>; // 11
type WithZero = TS.Numeric.Summ<0, 3>; // 3
type Negative = TS.Numeric.Summ<-8, 3>; // -5
type Large = TS.Numeric.Summ<20000, 997>; // 20997

TS.Numeric.Diff<X, Y>

Calculate X - Y. Uses an optimized algorithm to avoid the 999 iteration limit.

Example:

import { TS } from '@avstantso/ts';

type Simple = TS.Numeric.Diff<8, 3>; // 5
type WithZero = TS.Numeric.Diff<0, 3>; // -3
type Negative = TS.Numeric.Diff<-8, 3>; // -11
type Large = TS.Numeric.Diff<20000, 997>; // 19003

TS.Numeric.Multiply<X, Y>

Calculate X * Y.

Limitation: One of X or Y must be in range [-1000, 1000]. Beyond this range, you may encounter "Type instantiation is excessively deep" errors.

Example:

import { TS } from '@avstantso/ts';

type Simple = TS.Numeric.Multiply<8, 3>; // 24
type WithZero = TS.Numeric.Multiply<0, 3>; // 0
type Negative = TS.Numeric.Multiply<-8, 3>; // -24
type Large = TS.Numeric.Multiply<900000, -1000>; // -900000000

TS.Numeric.Div<X, Y>

Calculate X / Y. Returns quotient if evenly divisible, otherwise [quotient, remainder]. Returns never for division by zero.

Limitation: One of X or Y must be in range [-1000, 1000].

Example:

import { TS } from '@avstantso/ts';

type DivByZero = TS.Numeric.Div<8, 0>; // never
type Zero = TS.Numeric.Div<0, 3>; // 0

type NotInt = TS.Numeric.Div<1, 3>; // null

type Simple1 = TS.Numeric.Div<8, 2>; // 4
type Simple2 = TS.Numeric.Div<8, 3>; // [2, 2] (quotient 2, remainder 2)

type Equal = TS.Numeric.Div<-68899, -68899>; // 1
type NegResult = TS.Numeric.Div<-34, 7>; // [-4, -6]

type MaxRange = TS.Numeric.Div<999999, 1000>; // [999, 999]

TS.Numeric.Power<X, E>

Calculate X ^ E. If E is negative, returns never.

Limitation: Result must be within Numeric.Domain.Power range.

Example:

import { TS } from '@avstantso/ts';

type Pow1 = TS.Numeric.Power<3, 6>; // 729
type Pow2 = TS.Numeric.Power<3, 7>; // 2187
type NegBase1 = TS.Numeric.Power<-2, 1>; // -2
type NegBase2 = TS.Numeric.Power<-2, 2>; // 4

TS.Literal

Core type definitions by their name literals. Provides a system for working with type names as strings.

Literal Types

TS.Literal

Union of literals for available value types.

TS.Literal.Map

Map of type name literals to actual types.

export interface AVStantso.TS.Literal.Map extends AtomicObjects {
  string: string;
  number: number;
  bigint: bigint;
  boolean: boolean;
  symbol: symbol;
  undefined: undefined;
  object: object;
  function: Function;
}

You can extend this interface to add custom type literals.

TS.Literal.NumberLike

Map for number-like type names (key is significant, value ignored).

export interface AVStantso.TS.Literal.NumberLike {
  number: 0;
  bigint: 0;
  Date: 0;
}

TS.Literal.IsNumberLike<L, IfTrue = true, IfFalse = false>

Test if literal L represents a number-like type.

Example:

import { TS } from '@avstantso/ts';

type IsNum = TS.Literal.IsNumberLike<'number'>; // true
type IsObj = TS.Literal.IsNumberLike<'object'>; // false

TS.Literal.StringLike

Map for string-like type names (key is significant, value ignored).

export interface AVStantso.TS.Literal.StringLike {
  string: 0;
  Buffer: 0;
}

TS.Literal.IsStringLike<L, IfTrue = true, IfFalse = false>

Test if literal L represents a string-like type.

Example:

import { TS } from '@avstantso/ts';

type IsStr = TS.Literal.IsStringLike<'string'>; // true
type IsObj = TS.Literal.IsStringLike<'object'>; // false

TS.Literal.List

Array of literals for available value types. Based on TS.Union.ToTuple<Literal>.

TS.Literal.Key2KeyRec

Literals key-to-key record for convenient comparisons.

Literal Runtime Utilities

TS.Literal

Runtime object with properties from Literal.Key2KeyRec and utility methods.

TS.Literal.List

Runtime array of literal strings.

Example:

import { TS } from '@avstantso/ts';

console.log(TS.Literal.List); // ['string', 'number', 'bigint', ...]
TS.Literal.Empty(type)

Get empty value for a literal type. Has getter properties for each registered literal.

Example:

import { TS } from '@avstantso/ts';

const emptyStr = TS.Literal.Empty('string'); // ''
const emptyNum = TS.Literal.Empty('number'); // 0
const emptyObj = TS.Literal.Empty('object'); // {}
TS.Literal.IsValue(type, value)

Test if value is of the specified literal type. Has function binding properties for each registered literal.

Example:

import { TS } from '@avstantso/ts';

console.log(TS.Literal.IsValue('string', 'hello')); // true
console.log(TS.Literal.IsValue('number', 'hello')); // false

// Using bound functions
console.log(TS.Literal.IsValue.string('hello')); // true
TS.Literal._Register(literal, empty?)

Register a custom type literal for extension.

Example:

import { TS } from '@avstantso/ts';

type XYZ = { x: string; y: number; z: boolean };

// Extend the namespace
namespace AVStantso.TS.Literal {
  export interface Map {
    xyz: XYZ;
  }
}

// Register the literal
avstantso.TS.Literal._Register('xyz');

// Now you can use it
type Resolved = AVStantso.TS.Resolve<'xyz'>; // XYZ
console.log(avstantso.TS.Literal.List.includes('xyz')); // true

TS.Type

Type manipulation and definition utilities.

Type Types

TS.Type

Union of all available value types: string | number | bigint | boolean | symbol | object | Function | Date | Buffer.

TS.Type.Not<T>

Exclude specified type T from available types.

TS.Type.Not.Function

Available types excluding Function: Exclude<Type, Function>.

TS.Type.Not.Object

Available types excluding object: Exclude<Type, object>.

TS.Type.Not.String

Available types excluding string: Exclude<Type, string>.

TS.Type.Def

Type definition structure supporting Literal.

TS.Type.KeyDef

Keyed type definition structure.

TS.Type.KLD

Type definition array with key and optional default: [<key>, <type literal>, <default value>?].

TS.Type.Union<T>

Type union of T with Literal.

Example:

import { TS } from '@avstantso/ts';

type Never = TS.Type.Union<never>; // never
type Undef = TS.Type.Union<undefined>; // unknown

// Literals NOT supported as strings:
type LiteralStr = TS.Type.Union<string | 'bigint'>; // string

type WithLiteral = TS.Type.Union<number, 'string' | 'bigint'>; // number | 'string' | 'bigint'

type FromDef = TS.Type.Union<{ T: Function; L: 'boolean' }>; // 'boolean' | Function

type WithObject = TS.Type.Union<object>; // object | Literal

Type Runtime Utilities

TS.Type.KeyDef(key, type)

Create keyed type definition structure at runtime.

Example:

import { TS } from '@avstantso/ts';

const keyDef = TS.Type.KeyDef('id', 'string');
// { K: 'id', L: 'string' }

TS.Type.KLD(key, type, def?)

Create type definition array [<key>, <type literal>, <default value>?].

Example:

import { TS } from '@avstantso/ts';

const kld = TS.Type.KLD('id', 'string', '');
// ['id', 'string', '']

TS.Resolve

Type literal resolution utilities for converting literal type names to actual types.

TS.Resolve<T>

Resolve Literal in type union T to their actual types.

Example:

import { TS } from '@avstantso/ts';

type Never = TS.Resolve<never>; // never
type Undef = TS.Resolve<undefined>; // unknown

// Literal strings NOT supported as type literals:
type StrWithLiteral = TS.Resolve<string | 'function'>; // string

type LiteralUnion = TS.Resolve<'bigint' | 'string'>; // string | bigint

type Direct = TS.Resolve<bigint>; // bigint

type Mixed = TS.Resolve<'bigint' | 'string' | boolean>; // string | bigint | boolean

type FromDef = TS.Resolve<{ T: Function; L: 'boolean' }>; // boolean | Function

type EmptyObj = TS.Resolve<{}>; // {}

type DefWithBase = TS.Resolve<{ T: string; L: 'string' | 'boolean' }>; // string | boolean

type DefMixed = TS.Resolve<{ T: string; L: 'function' }>; // string | Function

type OnlyLiteral = TS.Resolve<{ L: 'function' }>; // Function

type OnlyType = TS.Resolve<{ T: Function }>; // Function

TS Utility Types

Miscellaneous utility types for advanced type manipulation.

TS.Alt<T>

Create object with alternative fields (only one field at a time, not all simultaneously).

If T is a structure object, each field becomes an alternative. If T is an array, each item becomes an alternative.

Example:

import { TS } from '@avstantso/ts';

type Obj = { a: number; b: string; c: { x: bigint } };
type AltObj = TS.Alt<Obj>;
// {
//   a: number;
//   b?: never;
//   c?: never;
// } | {
//   a?: never;
//   b: string;
//   c?: never;
// } | {
//   a?: never;
//   b?: never;
//   c: { x: bigint };
// }

type Arr = [{ a: number; b: string }, { c: { x: bigint }; d: unknown }];
type AltArr = TS.Alt<Arr>;
// {
//   a: number;
//   b: string;
//   c?: never;
//   d?: never;
// } | {
//   a?: never;
//   b?: never;
//   c: { x: bigint };
//   d: unknown;
// }

TS.Flat<T, Depth = 1>

Flatten object structure to specified depth.

Example:

import { TS } from '@avstantso/ts';

type Nested = {
  v: () => Buffer;
  w: (() => string) & { n: string };
  x: { a: string; b: number };
  y: { c: { d: boolean } };
  z: bigint;
};

type Flat1 = TS.Flat<Nested>;
// {
//   v: () => Buffer;
//   z: bigint;
//   n: string;
//   a: string;
//   b: number;
//   c: { d: boolean };
//   w: () => string;
// }

type Flat2 = TS.Flat<Nested, 2>;
// {
//   v: () => Buffer;
//   z: bigint;
//   n: string;
//   a: string;
//   b: number;
//   d: boolean;
//   w: () => string;
// }

TS.IfDef<TBase, TExtended, TElse = TBase>

Select TExtended if defined, otherwise TBase or TElse.

TS.IfDefKey<TKey, TBase, TExtended, TElse = TBase[TKey]>

Select TExtended[TKey] if defined, otherwise TBase[TKey] or TElse.

Example:

import { TS } from '@avstantso/ts';

type A = {
  x?: number;
  y?: number;
};

type B = {
  x?: 1 | 2 | 3;
};

type XType = TS.IfDefKey<'x', A, B>; // 1 | 2 | 3
type YType = TS.IfDefKey<'y', A, B>; // number

TS.Opaque<TypeMeta, T>

Create opaque type that prevents direct assignment (nominal typing).

Example:

import { TS } from '@avstantso/ts';

type ID = TS.Opaque<'ID', string>;

// @ts-expect-error Type 'string' is not assignable to type 'ID'
const id1: ID = 'abc';

const id2: ID = 'def' as ID; // OK

const s: string = id1 + id2; // OK - can use as string

TS.Options<TTypeMap, TDefaults>

Options type for declarations with type mapping and defaults.

Override Types

TS.Override<TBase, TExtended, TOptional = false>

Override TBase properties with TExtended properties (only where TExtended[K] is not undefined).

Example:

import { TS } from '@avstantso/ts';

type A = {
  x?: number;
  y?: number;
  z?: number;
};

type B = {
  x?: 1 | 2 | 3;
  y?: 12;
};

type Result = TS.Override<A, B>;
// { x?: 1 | 2 | 3; y?: 12; z?: number }

TS.IfIsOverrided<TBase, TCurrent, IfTrue = true, IfFalse = false>

Test if TBase was overridden by TCurrent.

Example:

import { TS } from '@avstantso/ts';

type Overridden = TS.IfIsOverrided<number, 1 | 2 | 3>; // true
type NotOverridden = TS.IfIsOverrided<number, number>; // false
type UnknownBase = TS.IfIsOverrided<unknown, unknown>; // false
type UnknownOverridden = TS.IfIsOverrided<unknown, {}>; // true

TS.IfIsOverridedKey<TKey, TBase, TCurrent, IfTrue = true, IfFalse = false>

Test if TBase[Key] was overridden by TCurrent[Key].

Example:

import { TS } from '@avstantso/ts';

type Overridden = TS.IfIsOverridedKey<
  'a',
  { a: number; b: string },
  { a: 1 | 2 | 3; b: string }
>; // true

type NotOverridden = TS.IfIsOverridedKey<
  'a',
  { a: number; b: string },
  { a: number; b: string }
>; // false

TS.IfNotOverrided<TBase, TCurrent, TExtended>

Select TExtended if TBase and TCurrent are equal.

Example:

import { TS } from '@avstantso/ts';

type Overridden = TS.IfNotOverrided<number, 1 | 2 | 3, 2>; // 1 | 2 | 3
type NotOverridden = TS.IfNotOverrided<number, number, 4>; // 4

TS.IfNotOverridedKey<TKey, TBase, TCurrent, TExtended>

Select TExtended[TKey] if TBase[TKey] and TCurrent[TKey] are equal.

TS.OverrideIfNot<TBase, TCurrent, TExtended, TOptional = false>

Override TCurrent properties with TExtended properties only where TCurrent[K] equals TBase[K].

Example:

import { TS } from '@avstantso/ts';

type A = {
  a?: string;
  b?: string;
  x?: number;
  y?: number;
  z?: number;
};

type B = {
  x?: 1 | 2 | 3;
  y?: 12;
};

type C = {
  b: 'b' | 'bb';
  x?: 4;
  z?: 72;
};

type Result = TS.OverrideIfNot<A, B, C>;
// {
//   a?: string;     // from A (not in B & C)
//   b?: 'b' | 'bb'; // from C (not in B)
//   x?: 1 | 2 | 3;  // from B (overridden in B)
//   y?: 12;         // from B
//   z?: 72;         // from C (not in B)
// }

TS.ReplaceKey<TKey, TBase, TReplacement, TOptional = false>

Replace key TKey in object or function TBase with TReplacement.

Example:

import { TS } from '@avstantso/ts';

type Required = TS.ReplaceKey<'a', { a: string; b: number }, []>;
// { a: []; b: number }

type Optional = TS.ReplaceKey<'a', { a: string; b: number }, [], true>;
// { a?: []; b: number }

TS.ReplaceKeyOpt<TKey, TBase, TReplacement>

Replace key TKey optionally (equivalent to ReplaceKey<TKey, TBase, TReplacement, true>).

TS.RequiredKeys<T>

Get union of required keys from type T.

Example:

import { TS } from '@avstantso/ts';

type Keys = TS.RequiredKeys<{ a: 1; b?: 2 }>; // 'a'

TS.OptionalKeys<T>

Get union of optional keys from type T.

Example:

import { TS } from '@avstantso/ts';

type Keys = TS.OptionalKeys<{ a: 1; b?: 2 }>; // 'b'

TS.Merge<Base, Extended>

Merge types. Combines fields for objects, creates union for other types.

Example:

import { TS } from '@avstantso/ts';

type UnionTypes = TS.Merge<number, string>; // number | string
type MergeObjects = TS.Merge<{ a?: number; b?: string }, { a: string }>;
// { a: string; b?: string }

TS.Merge.Fields<Base, Extended, BaseKey, ExtendedKey = BaseKey>

Merge specific fields of object types.

Example:

import { TS } from '@avstantso/ts';

type FieldA = TS.Merge.Fields<{ a?: number; b?: string }, { a: string }, 'a'>;
// number | string

type FieldB = TS.Merge.Fields<{ a?: number; b?: string }, { a: string }, 'b', 'a'>;
// string

Utility Runtime Functions

TS.isKey<K extends AVStantso.TS.Key>(candidate: unknown): candidate is K

Check if candidate has object key type (string, number, or symbol).

Example:

import { TS } from '@avstantso/ts';

const key: unknown = 'myKey';
if (TS.isKey(key)) {
  // key is string | number | symbol
  const obj = { [key]: 'value' };
}

TS.flat(structure, depth = 1)

Flatten structure object to specified depth.

Warning: Creates wrappers for functions with extended properties. The this context will be lost.

Example:

import { TS } from '@avstantso/ts';

const data = {
  a: 15,
  b: {
    c: {
      s: 'my string'
    }
  },
  d: () => 4
};

const flat1 = TS.flat(data);
// {
//   a: 15,
//   c: { s: 'my string' },
//   d: [Function]
// }

const flat2 = TS.flat(data, 2);
// {
//   a: 15,
//   s: 'my string',
//   d: [Function]
// }

Requirements

  • Node.js 12.0 or higher
  • TypeScript 4.0 or higher (for TypeScript projects)

Dependencies

License

MIT - See LICENSE file for details

Repository

GitLab - avstantso-js/cross-platform-utils

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests to the repository.