Basic data structures and algorithms. Built on @rickosborne/typical for types, and @rickosborne/guard for guards.
Install via your favorite package manager.
Each package supports CommonJS require
, ESM import
, and TypeScript usage.
You also have a choice: barrel imports or direct imports.
Barrel imports mean you're going to require/import everything from the same package-level namespace:
// CommonJS
const { isPlainObject, isListOf } = require("@rickosborne/guard");
// ESM / TypeScript
import { isPlainObject, isListOf } from "@rickosborne/guard";
Implications:
- Nice and simple.
- Your build system needs to do tree-shaking well ... or you'll end up adding the entire package even if you only import two functions.
The other option is to use direct imports:
// CommonJS
const { isPlainObject } = require("@rickosborne/guard/is-object");
const { isListOf } = require("@rickosborne/guard/is-list-of");
// ESM / TypeScript
import { isPlainObject } from "@rickosborne/guard/is-object.js";
import { isListOf } from "@rickosborne/guard/is-list-of.js";
Implications:
- You (probably) don't have to worry about tree-shaking as your build (likely) ends up with only the functions you need.
If you're using a modern build system, there aren't any strong reasons to prefer one way over the other. It's really just down to your personal preference.
Do you need to use file extensions? And if so, which extensions?
Honestly ... this is a dumpster fire question. It really comes down to your own setup and configuration.
Within each package itself:
- The CommonJS files all have
.cjs
extensions. - The ESM files all have
.mjs
extensions. - Node subpath exports have been set up to send
.js
imports to the.cjs
(viarequire
) or.mjs
(viaimport
) files, depending on your setup.
So, in theory, the only extension which won't work would be .ts
because the source isn't included.
If you run into a problem with a particular configuration, file a GitHub issue with:
- Your
tsconfig.json
'smodule
,moduleResolution
, andtarget
settings. - Your
package.json
'stype
andimports
settings. - An example of another package which imports correctly for you.
This package is licensed as CC-BY-NC-SA-4.0 unless otherwise noted. That is, Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
class ArrayBinaryMinHeap<T> implements Queue<T>
Simple implementation of a binary min-heap, meaning low values are sorted before high values, using the supplied comparator. Invert your comparator if you want a max-heap.
abstract class AsyncIteratorTransformer<InputT, OutputT> extends IteratorTransformerBase<InputT, OutputT> implements AsyncIterableIterator<OutputT, undefined, undefined>
class AsyncStringTokenizer extends AStringTokenizer
abstract class IteratorTransformer<InputT, OutputT> extends IteratorTransformerBase<InputT, OutputT> implements IterableIterator<OutputT, undefined, undefined>
abstract class IteratorTransformerBase<InputT, OutputT>
Basic queues and statistic tracking for a dual-queued Iterator transformer.
class JsonParseObserver
class JsonPushTokenizer
class MultiAsyncIterator<T> implements AsyncIterable<T>
Wrapper for an AsyncIterator which allows multiple consumers to read from the same iterable via a basic queue which tracks which consumers have read which values.
class PriorityArray<T> implements Queue<T>
An implementation of a priority queue backed by a JS array, using the given comparator. Sorts low-to-high, so you will need to invert comparator if you want high-to-low.
class PriorityLinkedList<T> implements Queue<T>
Implementation of a priority queue backed by a linked list, using the given comparator. Sorts low-to-high, so you will need to invert comparator if you want high-to-low.
class SkipList<T> implements Queue<T>
Basic skip list implementation, using the given comparator to keep values in order, low-to-high. If you want high-to-low you will need to invert your comparator.
class StringTokenizer extends AStringTokenizer
Primitive string tokenizer upon which parsers could be built.
class TimeoutError extends Error
Error which will be thrown if a timeout happens and no other error is provided.
abstract class TokenGenerator<TokenT> extends AsyncStringTokenizer implements AsyncIterable<TokenT>
class UnknownError extends Error
An error thrown when the root problem is unknown.
addProperties: <T, K extends string, R extends Record<K, TypedPropertyDescriptor<unknown>>>(target: T, descriptors: R) => Resolve<T & PropertiesFromDescriptors<R>>
A more type-friendly version of Object.defineProperties. See Object.defineProperties on MDN.
addProperty: <T, K extends string, V, D extends TypedPropertyDescriptor<V>>(target: T, key: K, descriptor: D) => Resolve<T & PropertyFromDescriptor<K, D>>
A more type-friendly version of Object.defineProperty. See Object.defineProperty on MDN.
arrayBinaryMaxHeap: <T>(comparator: Comparator<T>) => ArrayBinaryMinHeap<T>
Build a max-heap using the given comparator. Will invert the comparator and build a min-heap, which produces the same outcomes.
arrayBinaryMinHeap: <T>(comparator: Comparator<T>) => ArrayBinaryMinHeap<T>
Build a min-heap using the given comparator.
arrayEq: <T>(a: T[], b: T[], predicate?: ((a: T, b: T, index: number) => boolean)) => boolean
Simple comparison to see if two arrays are equivalent.
arrayFromAsync: <T>(iterableOrArrayLike: AsyncIterable<T> | Iterable<T | PromiseLike<T>> | ArrayLike<T | PromiseLike<T>>) => Promise<T[]>
Polyfill for Array.fromAsync
for node before v22.
arrayUnique: <T>(array: T[]) => T[]
Generate a new array which has no duplicate values. Preserves the order of the first occurrence of each value. Returns the original array if no duplicates were found.
asFraction: (num: number, percentError?: number) => FracTuple
Try to find a human-readable fraction for the given decimal value, within a given percentage error. See the original algorithm by Sjaak.
asIndexKey: (key: string) => number | undefined
Try to convert the string-format key into an array index key.
asyncIteratorFrom: <TYield, TReturn, TNext>(iterator: Iterator<TYield, TReturn, TNext>) => AsyncIterator<TYield, TReturn, TNext>
Convert a synchronous iterator into an asynchronous one.
asyncIteratorOf: <T>(it: AsyncIterable<T, undefined, undefined> | Iterable<T, undefined, undefined> | AsyncIterator<T, undefined, undefined>) => AsyncIterator<T, undefined, undefined>
If the value is already an Iterator, return it. If the value is AsyncIterable, return an Iterator for it. It the value is Iterable, upgrade an Iterator for it to an AsyncIterator and return that. Otherwise, throw an error.
asyncIteratorTransformer: <InputT, OutputT>(map: (inputs: InputT[], inputIsDone: boolean) => IteratorTransformerMapResult<OutputT> | Promise<IteratorTransformerMapResult<OutputT>>, options?: AsyncIteratorTransformerOptions) => (it: AsyncIterator<InputT, undefined, undefined> | AsyncIterable<InputT, undefined, undefined> | Iterable<InputT, undefined, undefined>) => AsyncIteratorTransformer<InputT, OutputT>
binaryIndexOf: <T>(value: T, items: T[], comparator: Comparator<T>, config?: BinaryIndexOfConfig) => SearchResult
Perform a binary search through the given list for the given value using the given comparator.
catchAnd: <T, O extends CatchAndOptions<T>>(options?: O) => (err: unknown) => CatchAndReturn<T, O>
Catch block builder to reduce the noise of thorough error handling.
chainableComparator: <T>(comparator: Comparator<T>) => ChainableComparator<T>
Wrap the given comparator so you can chain ChainableComparator functions from it.
closeTo: (a: number, b: number, epsilon?: number) => boolean
Test for whether two numbers are close enough to each other, within an acceptable margin.
closeToZero: (n: number, epsilon?: number) => n is 0
Test for whether a number is close enough to zero, within an acceptable margin.
comparatorBuilder: <T>() => ComparatorBuilder<T>
Start building a comparator.
computeIfAbsent: <T, K>(key: K, map: Map<K, T>, compute: (key: K) => T) => T
Find the item in the Map, or compute and store it.
concatRegExp: (...patterns: RegExp[]) => RegExp
Concatenate the patterns (and flags) of regular expressions so they will match all at once. This does not attempt to fix any problems, such as duplicate named capture groups or incorrectly-numbered backreferences.
deepCopy: <T>(source: T, options?: DeepCopyOptions) => T
Create a deep copy of an object. This is not a particularly robust check, and won't copy things like class instances.
function deepEquals<T>(actual: unknown, expected: T): actual is T;
Recursively compare two objects for equivalence. Warning: does not attempt to resolve cycles.
deepMerge: <Loser, Winner>(loser: Loser, winner: Winner) => DeepMerge<Loser, Winner>
Recursively merge two values, if possible. See DeepMerge for details on the logic.
deepSort: <T>(obj: T, options?: DeepSortOptions) => T
Sort an object, and any objects nested through plain objects or arrays, by key, so when JSON stringified you will get a deterministic output.
divMod: (num: number, divisor: number) => [quotient: number, remainder: number]
Euclidian division which returns a tuple of the quotient and remainder.
doubleLinkedList: <T>() => DoubleLinkedList<T>
Build a doubly-linked list.
entriesOf: <T extends object>(obj: T) => [keyof T, T[keyof T]][]
A wrapper for Object.entries
which has typed keys and values.
findConsole: () => ConsoleLike
formatBytes: (bytes: number | bigint, base?: 1024 | 1000, precision?: number) => string
Pretty-print a byte value with low enough detail to be quickly human-readable.
formatDuration: (duration: Duration) => string
formatMarkdownTable: <T extends object>(values: T[], options: FormatMarkdownTableOptions<T>) => string
Generate a Markdown-formatted table for the given items.
function holder<T>(value: T): ValuedHolder<T>;
function holder<T>(): EmptyHolder<T>;
imprecise: (num: number, resolution?: number) => string
String-format a number rounded to the given resolution, where human readability is more important than precision.
isConsoleLike: (obj: unknown) => obj is ConsoleLike
isSvgAbsolutePathCommand: (value: unknown) => value is SvgAbsolutePathCommand
isSvgPathCommand: (value: unknown) => value is SvgPathCommand
isSvgRelativePathCommand: (value: unknown) => value is SvgRelativePathCommand
iteratorOf: <T>(it: Iterable<T, undefined, undefined> | Iterator<T, undefined, undefined>) => Iterator<T, undefined, undefined>
If the value is already an Iterator, return it. If the value is Iterable, return an Iterator for it. Otherwise, throw an error.
iteratorTransformer: <InputT, OutputT>(map: (inputs: InputT[], inputIsDone: boolean) => IteratorTransformerMapResult<OutputT>) => (it: Iterator<InputT, undefined, undefined> | Iterable<InputT, undefined, undefined>) => IteratorTransformer<InputT, OutputT>
function jsonParseEventsOf(...its: StringIterable[]): Generator<JsonParseEvent, void, undefined>;
function jsonParseEventsOfAsync(...its: AsyncStringIterable[]): AsyncGenerator<JsonParseEvent, void, undefined>;
jsonPathAppend: (path: string, key: string | number | symbol, options?: JsonPathAppendOptions) => string
Append the given property key to the given JSON Path expression. This does not attempt to validate anything about the path or the key, only formats it according to very basic rules. Technically, the spec doesn't handle symbol values, so if you give it a path with a symbol you get an expression which other JSON Path parsers can't handle. However, it does use the correct function syntax, so it should still at least parse correctly.
function jsonTokensOf(...its: StringIterable[]): Generator<JsonToken, void, undefined>;
function jsonTokensOfAsync(...its: AsyncStringIterable[]): AsyncGenerator<JsonToken, void, undefined>;
function lowerFirst(text: string): string;
function lowerFirst(text: string | null | undefined): string | undefined;
memoize: <T>(supplier: Supplier<T>) => Supplier<T>
Shorthand for memoizeSupplier.
memoizeSupplier: <T>(supplier: Supplier<T>) => Supplier<T>
Memoize the given supplier so that it is called at most once.
function minMax(values: number[]): [number, number];
function minMax(...values: number[]): [number, number];
optionalRegExp: (pattern: RegExp) => RegExp
Modify a regular expression's pattern to make the entire expression optional, keeping any start/end anchors in place
parseDuration: (text: string) => DurationWithText
Parse an ISO-8601 duration from the given text. If the text contains extra non-duration characters after, will only throw an error if they would produce an ambiguous result, or could indicate an incomplete duration.
parseLocalDate: (text: string, config?: ParseLocalDateConfig) => Date
Parse an ISO-8860-like date, but do so assuming that the time is intended to be local, not UTC. But if allowed, the date could override this with specific time zone info.
positiveDiv: (num: number, divisor: number) => number
Modulo where the result is always positive.
positiveMod: (num: number, divisor: number) => number
Modulo where the result is always positive.
priorityArray: <T>(comparator: Comparator<T>) => Queue<T>
Build a priority queue which uses an array as a backing store.
priorityLinkedList: <T>(comparator: Comparator<T>) => Queue<T>
Build a priority queue which uses a linked list as a backing store.
randomNumberGenerator: (seedOrOptions?: number | RNGOptions, presetName?: LCEPresetName | undefined) => RNG
https://en.wikipedia.org/wiki/Linear_congruential_generator
reduceToUnique: <T>() => [(prev: T[], cur: T) => T[], T[]]
Generate the args for an array reducer which keeps only distinct values.
reQuote: (text: string, options?: ReQuoteOptions) => string
Given a text, either wrap it in quotes which make the most sense for the text, or change the quotes to a different set.
function resolvablePromise<T>(): ResolvablePromise<T>;
Build a promise which can be resolved from the outside.
roundTo: (value: number, resolution?: number) => number
Round a given number to the nearest unit of resolution. For resolution of 1, this is equal to Math.round
.
secondsFromDuration: (duration: Partial<DurationWithText>) => number
Convert a given duration to an equivalent number of seconds.
shuffle: <T>(list: T[], { into, random01 }?: ShuffleConfig<T>) => T[]
Fisher-Yates shuffle. Defaults to in-place sorting, but can sort into a new one via into.
simpleStarMatch: (glob: string, text: string) => boolean
Match the given simple-* glob against the given text. This does not use "filesystem glob" logic. That is, a *
here will match anything, including /
. Similarly, there is no ?
operator.
function singleCharactersOf(...its: StringIterable[]): Generator<string, void, unknown>;
function singleCharactersOfAsync(...its: AsyncStringIterable[]): AsyncGenerator<string, void, unknown>;
singleLinkedList: <T>() => List<T>
Builder for a single-linked list.
skipList: <T>(comparator: Comparator<T>) => SkipList<T>
Build a priority queue using a skip list implementation.
function sleep<T>(ms: number, value: T): Promise<T>;
Sleep at least some number of ms, returning the supplied value when complete.
function sleep(ms: number): Promise<undefined>;
Sleep at least some number of ms.
splitFixed: (text: string, width: number) => string[]
Split a string into fixed-width substrings. The last one may be short.
starMatchParts: (glob: string) => StarGlobPart[]
Parse a simple-* glob into its constituent tokens.
function svgPathCommandsOf(...d: StringIterable[]): Generator<SvgPathToken, void, undefined>;
Parse an SVG path
definition into drawing commands.
function svgPathValuesOf(...d: StringIterable[]): Generator<SvgPathValue, void, undefined>;
Tokenize an SVG path
definition into command
, number
, and space
tokens.
toBatches: <T>(maxPerBatch: number, list: T[], mode?: ToBatchesMode) => T[][]
Group the given list into batches of the given maximum count, optionally using a given strategy.
toBatchesReducer: <T>(maxPerBatch: number, mode?: ToBatchesMode) => [reduce: (prev: T[][], cur: T, index: number, list: T[]) => T[][], initial: T[][]]
Generate an array reducer which will group the given list into batches of the given maximum count, optionally using a given strategy.
toShuffled: <T>(list: T[], config?: Omit<ShuffleConfig<T>, "into"> | undefined) => T[]
Wrapper for the shuffle function which shuffles into a new array, leaving the original intact.
uniqueReducer: () => <T>(prev: T[], cur: T) => T[]
Generate a function for use in an array reducer which will track and only keep the first occurrence of each value.
function window2<T>(items: Readonly<T[]>): Generator<Readonly<[T, T, number, number]>, void, undefined>;
Generator for a sliding window of pairs of values from the given list. It yields each value in the list in a tuple with its successor. The last item wraps around to use the first item as its successor. The indices of the two values are also yielded after the values. For example:
for (const [ x, y, xIndex, yIndex ] of window2([ "a", "b", "c" ])) {
console.log(x, y, xIndex, yIndex);
}
This would output:
a, b, 0, 1 b, c, 1, 2 c, a, 2, 0
function window3<T>(items: Readonly<T[]>): Generator<Readonly<[T, T, T, number, number, number]>, void, undefined>;
Generator for a sliding window of triplets of values from the given list. It yields each value in the list in a tuple with its predecessor and successor. The first and last items wrap around to use the last and first items as their predecessor/successor. The indices of the values are also provided after the values. The middle value (y in the example below) is the "current" value, with the first value (x) being its predecessor and the third (z) its successor. That current value is the one which will be at index 0 for the first iteration of the loop. For example:
for (const [ x, y, z, xIndex, yIndex, zIndex ] of window3([ "a", "b", "c" ])) {
console.log(x, y, z, xIndex, yIndex, zIndex);
}
This would output:
c, a, b, 2, 0, 1 a, b, c, 0, 1, 2 b, c, a, 1, 2, 0
withLazyProperty: <Target, Property, Name extends string>(target: Target, name: Name, calculator: (t: Target) => Property) => WithProperty<Target, Name, Property>
Add a property to the given object which is calculated lazily, and only once.
withNullsFirst: <T>(comparator: Comparator<T>) => Comparator<T | null | undefined>
Wrap the given comparator to return null and undefined values before the others.
withNullsLast: <T>(comparator: Comparator<T>) => Comparator<T | null | undefined>
Wrap the given comparator to return null and undefined values after the others.
function withTimeout<T>(options: WithTimeoutOptions<T>): Promise<T>;
Wrap a given block or promise in another promise which will resolve or reject if the first has not resolved within the specified time limit.
zeroPad: (num: number, length: number, radix?: number) => string
Convert a number to a string and left-pad it out to the given length with zeroes.
export interface ArcSvgPathToken extends SvgPathTokenBase<"arc">
export interface AsyncIteratorTransformerOptions
Additional configuration for an asynchronous Iterator transformer.
export interface CatchAndOptions<T>
export interface CloseSvgPathToken extends SvgPathTokenBase<"close">
export interface CommandSvgPathValue extends SvgPathValueBase<"command">
export interface ConsoleLike
export interface CubicCurveSvgPathToken extends SvgPathTokenBase<"cubic">
export interface DeepCopyOptions
export interface DeepSortOptions
export interface Duration
ISO8601-like measure of a duration. Does not include any concept of being relative to any specific date.
export interface DurationWithText extends Duration
A duration parsed from text, which includes the extracted (serialized) duration text.
export interface EmptyHolder<T> extends Holder<T>
A Holder without a value, yet.
export interface FormatMarkdownTableOptions<T extends object>
Options for formatMarkdownTable.
export interface Holder<T>
A structure which can hold any value type, even undefined, and can itself be const, while still allowing the value to be added later.
export interface IteratorTransformerMapResult<OutputT>
export interface JsonBooleanToken extends JsonTokenBase
export interface JsonNullToken extends JsonTokenBase
export interface JsonNumberToken extends JsonTokenBase
export interface JsonParseArrayState extends JsonParseStateBase
export interface JsonParseItemState extends JsonParseStateBase
export interface JsonParseObjectState extends JsonParseStateBase
export interface JsonParsePropertyState extends JsonParseStateBase
export interface JsonParseRootState extends JsonParseStateBase
export interface JsonParseStateBase
export interface JsonPathAppendOptions
export interface JsonPunctuationToken extends JsonTokenBase
export interface JsonSpaceToken extends JsonTokenBase
export interface JsonStringToken extends JsonTokenBase
export interface JsonTokenBase
export interface LineSvgPathToken extends SvgPathTokenBase<"line">
export interface LogLike
export interface MoveSvgPathToken extends SvgPathTokenBase<"move">
export interface NumberSvgPathValue extends SvgPathValueBase<"number">
export interface QuadraticCurveSvgPathToken extends SvgPathTokenBase<"quad">
export interface ResolvablePromise<T> extends Promise<T>
A promise which can be resolved from the outside.
export interface RNG
export interface RNGOptions
export interface SpaceSvgPathValue extends SvgPathValueBase<"space">
export interface SvgPathTokenBase<T extends keyof SvgPathTokenByType>
export interface SvgPathTokenByType
export interface SvgPathValueBase<T extends SvgPathValueType>
export interface SvgPathValueByType
export interface UnknownErrorOptions extends ErrorOptions
Options for UnknownError.
export interface ValuedHolder<T> extends Holder<T>
A Holder whose value has been set.
export interface WithTimeoutOptions<T>
Options for withTimeout.
type AsyncIteratorTransformerConstructor<InputT, OutputT> = AbstractConstructorLike<[iterator: AsyncIterator<InputT, undefined, undefined>], AsyncIteratorTransformer<InputT, OutputT>>;
type AsyncStringIterable = StringIterable | AsyncIterable<string, undefined, undefined> | AsyncIterator<string, undefined, undefined>;
type BinaryIndexOfConfig = {
firstNonUnique?: boolean;
initialLeft?: number;
initialRight?: number;
rangeCheck?: boolean;
};
Configuration options for binaryIndexOf.
type ChainableComparator<T> = Comparator<T> & {
get desc(): ChainableComparator<T>;
get nullsFirst(): ChainableComparator<T | undefined | null>;
get nullsLast(): ChainableComparator<T | undefined | null>;
};
Mixin for a comparator with chaining functions to constrain the behavior of the comparator.
type ComparatorBuilder<T> = {
build(): Comparator<T>;
get desc(): ComparatorBuilder<T>;
get nullsFirst(): ComparatorBuilder<T>;
get nullsLast(): ComparatorBuilder<T>;
num(accessor: (t: T) => (undefined | number)): ComparatorBuilder<T>;
str(accessor: (t: T) => (undefined | string)): ComparatorBuilder<T>;
};
Build a comparator for the given type, which goes through the specified checks in the order they are defined.
type DeepMerge<Loser, Winner> = Winner extends object ? Loser extends object ? ({
[K in keyof Loser as K extends keyof Winner ? never : K]: Loser[K];
} & {
[K in keyof Winner as K]: K extends keyof Loser ? DeepMerge<Loser[K], Winner[K]> : Winner[K];
}) : Winner : Winner;
Given two types, recursively compare and merge them with the following logic: 1. If the two types are different, Winner wins. 2. If either type is not a Record, Winner wins. 3. If both types are Records, each property, in the set of all keys from both, is compared using the same logic. A superset Record is created.
type DoubleLinkedList<T> = List<T> & {
get tail(): T | undefined;
reverseValues(): Generator<T, void, undefined>;
reverseValuesAndIndexes(): Generator<[T, number], void, undefined>;
reverseWalk(block: (value: T, index: number) => ListWalkDecision<T>): void;
};
Mixin for additional methods available when the linked list is double-linked.
type DurationDesignator = "Y" | "M" | "W" | "D" | "T" | "H" | "S";
ISO-8601 designator for a duration value.
type FracTuple = [numerator: number, denominator: number];
A fraction represented as a tuple of numerator and denominator. The numerator is negative if the value is negative. The denominator is always positive, and at least 1. Both values are integers, though the numerator may be Infinity or NaN as the value requires.
type GetPropertyDescriptor<T> = PropertyDescriptorFlags & {
get(): T;
set?: never;
value?: never;
};
Partial property descriptor which includes only an accessor (getter) and not a mutator, and is thus read-only.
type GetSetPropertyDescriptor<T> = PropertyDescriptorFlags & {
get(): T;
set(t: T): void;
};
Partial property descriptor which includes both an accessor (getter) and mutator (setter), and is thus read-write.
type IfReadOnlyDescriptor<T, D extends TypedPropertyDescriptor<unknown>> = D extends ReadOnlyPropertyDescriptor | GetPropertyDescriptor<unknown> ? T : never;
Filter type T based on whether the property descriptor D would produce a read-only property.
type IfReadWriteDescriptor<T, D extends TypedPropertyDescriptor<unknown>> = D extends ReadOnlyPropertyDescriptor | GetPropertyDescriptor<unknown> | SetPropertyDescriptor<unknown> ? never : T;
Filter type T based on whether the property descriptor D would produce a read-write (or write-only) property.
type IfWriteOnlyDescriptor<T, D extends TypedPropertyDescriptor<unknown>> = D extends SetPropertyDescriptor<unknown> ? T : never;
Filter type T based on whether the property descriptor D would produce a write-only property. Note: JS has a concept of a write-only property, and the unit tests cover this. However, TS doesn't have a way of expressing it, at least as of v5.8. So for now, it goes into the read-write bucket, even though you can't actually read from it. The alternative would be to set it to undefined
, to show you can't read from it ... but then you lose the type info for the setter. Yuck. For now ... The types below will, ahem, mangle the types they produce. Just a little. If you produce a setter-only property, it will end up looking like:
const withSetterOnly: WithSetterOnly = addProperty({}, "whatever", { set: (value: string) => void(whatever(value)) });
type WithSetterOnly = {
whatever: string;
whateverIsWriteOnly?: undefined;
}
So you get a reminder without breaking anything too hard.
type IntGenerator = Generator<number, void, undefined> & {
toArray(): number[];
};
Mixin for a generator which also has the ability to bundle its output into an array.
type IntGeneratorTo = {
toExclusive(stopExclusive: number): IntGenerator;
toInclusive(stopInclusive: number): IntGenerator;
};
Partial for the last step of an IntRange builder.
type IntRange = {
from(startInclusive: number): {
by(skip: number): IntGeneratorTo;
get down(): IntGeneratorTo;
get up(): IntGeneratorTo;
};
};
Integer range generators which (hopefully) make it super clear what your boundary, direction, and increment are.
type IteratorTransformerConstructor<InputT, OutputT> = SyncIteratorTransformerConstructor<InputT, OutputT> | AsyncIteratorTransformerConstructor<InputT, OutputT>;
type IteratorTransformerMore<T> = () => Optional<T>;
type JsonParseEvent = JsonParseBeginEvent<JsonParseState> | JsonParseEndEvent<JsonParseState>;
type JsonParseState = JsonParseObjectState | JsonParseArrayState | JsonParseItemState | JsonParsePropertyState | JsonParseRootState;
type JsonParseTypeT = (typeof JsonParseType)[keyof typeof JsonParseType];
type JsonPunctuation = "{" | "}" | "[" | "]" | ":" | ",";
type JsonToken = JsonNullToken | JsonBooleanToken | JsonNumberToken | JsonStringToken | JsonPunctuationToken | JsonSpaceToken;
type JsonTokenTypeT = (typeof JsonTokenType)[keyof typeof JsonTokenType];
type LCEPresetName = keyof typeof LCE_PRESETS;
type List<T> = {
at(index: number): T | undefined;
get head(): T | undefined;
insertAt(index: number, value: T): void;
get isEmpty(): boolean;
get length(): number;
pop(): T | undefined;
push(value: T): void;
shift(): T | undefined;
toArray(): T[];
unshift(value: T): void;
values(): Generator<T, void, undefined>;
valuesAndIndexes(): Generator<[T, number], void, undefined>;
walk(block: (value: T, index: number) => ListWalkDecision<T>): void;
readonly [Symbol.toStringTag]: string;
};
Basic list-like structure.
type ListWalkDecision<T> = {
deleteItem?: boolean;
insertAfter?: T;
insertBefore?: T;
keepWalking: boolean;
};
Controls how a List's walk operation behaves after each iteration.
type Optional<T> = {
value: T;
} | undefined;
type ParseLocalDateConfig = {
offsetMinutes?: number;
time?: boolean;
timeDelimiters?: string[];
zone?: boolean;
};
Configuration for a parseLocalDate call.
type PropertiesFromDescriptors<R extends Record<string, TypedPropertyDescriptor<unknown>>> = {
readonly [K in ReadOnlyDescriptorsKeys<R>]: R[K] extends TypedPropertyDescriptor<infer V> ? V : never;
} & {
[K in ReadWriteDescriptorsKeys<R>]: R[K] extends TypedPropertyDescriptor<infer V> ? V : never;
} & {
[K in WriteOnlyDescriptorsKeys<R>]: R[K] extends TypedPropertyDescriptor<infer V> ? V : never;
} & {
[K in RenamedWriteOnlyDescriptorsKeys<R>]?: undefined;
};
Produce an object with the properties described by the descriptors. See RenameIfWriteOnlyDescriptor for details on the mangling of write-only properties.
type PropertyDescriptorFlags = {
configurable?: boolean;
enumerable?: boolean;
writable?: boolean;
};
Basic flags for any property descriptor.
type PropertyFromDescriptor<K extends string, D extends TypedPropertyDescriptor<unknown>> = D extends TypedPropertyDescriptor<infer V> ? ({
readonly [key in IfReadOnlyDescriptor<K, D>]: V;
} & {
[key in IfReadWriteDescriptor<K, D>]: V;
} & {
[key in IfWriteOnlyDescriptor<K, D>]: V;
} & {
[key in RenameIfWriteOnlyDescriptor<K, D>]?: undefined;
}) : never;
Produce a single-property object type for the given property descriptor. Note: will produce an additional mangled pseudo-property for write-only properties. See RenameIfWriteOnlyDescriptor for details on the mangling.
type Queue<T> = {
add(value: T): void;
peek(): T | undefined;
remove(value: T): void;
get length(): number;
take(): T | undefined;
toArray(): T[];
values(): Generator<T, void, undefined>;
};
Basic interface for a queue.
type ReadOnlyDescriptorsKeys<R> = R extends Record<infer K, TypedPropertyDescriptor<unknown>> ? {
[key in K]: IfReadOnlyDescriptor<key, R[key]>;
}[K] : never;
Produce the keys for the given property descriptors record which would produce read-only properties.
type ReadOnlyPropertyDescriptor = {
writable: false;
};
Partial property descriptor which has been marked as non-writable.
type ReadWriteDescriptorsKeys<R> = R extends Record<infer K, TypedPropertyDescriptor<unknown>> ? {
[key in K]: IfReadWriteDescriptor<key, R[key]>;
}[K] : never;
Produce the keys for the given property descriptors record which would produce read-write (or write-only) properties.
type RenamedWriteOnlyDescriptorsKeys<R> = R extends Record<infer K, TypedPropertyDescriptor<unknown>> ? {
[key in string & K]: RenameIfWriteOnlyDescriptor<key, R[key]>;
}[string & K] : never;
Produce the mangled keys for the given property descriptors record which would produce write-only properties. See RenameIfWriteOnlyDescriptor for details on the mangling.
type RenameIfWriteOnlyDescriptor<Key extends string, D extends TypedPropertyDescriptor<unknown>> = D extends SetPropertyDescriptor<unknown> ? `${Key}IsWriteOnly` : never;
Mangle the given Key to ${Key}IsWriteOnly if property descriptor D would produce a write-only property.
type ReQuoteOptions = {
auto?: true;
quotes?: never;
} | {
auto?: never;
quotes?: string;
};
type SearchResult = {
before?: undefined;
comparisons: number;
exists: true;
index: number;
} | {
before: number;
comparisons: number;
exists: false;
index?: undefined;
};
A result of a search through a list. If the value was found, its index is returned. Otherwise, the before value is the index before which the value could be inserted. For troubleshooting and instrumentation, also returns the number of comparisons it took to find the value.
type SetPropertyDescriptor<T> = PropertyDescriptorFlags & {
get?: never;
set(t: T): void;
};
Partial property descriptor which includes only a mutator (setter) and not an accessor (getter), and is thus write-only. Note: TypeScript support for these kinds of properties is very poor as of v5.7.
type ShuffleConfig<T> = {
into?: T[] | undefined;
random01?: () => number;
};
Configuration options for the shuffle function.
type StarGlobPart = StarGlobText | StarGlobStar;
type StringIterable = string | Iterable<string, undefined, undefined> | Iterator<string, undefined, undefined>;
type SvgAbsolutePathCommand = "M" | "L" | "H" | "V" | "Z" | "C" | "S" | "Q" | "T" | "A";
type SvgPathCommand = SvgAbsolutePathCommand | SvgRelativePathCommand;
type SvgPathToken = SvgPathTokenByType[keyof SvgPathTokenByType];
type SvgPathValue = SvgPathValueByType[SvgPathValueType];
type SvgPathValueType = keyof SvgPathValueByType;
type SvgRelativePathCommand = Lowercase<SvgAbsolutePathCommand>;
type SyncIteratorTransformerConstructor<InputT, OutputT> = AbstractConstructorLike<[iterator: Iterator<InputT, undefined, undefined>], IteratorTransformer<InputT, OutputT>>;
type ToBatchesMode = typeof SPREAD_BATCHES | typeof FILL_BATCHES;
Strategy for grouping array items into batches.
type TypedPropertyDescriptor<T> = ValuePropertyDescriptor<T> | GetPropertyDescriptor<T> | SetPropertyDescriptor<T> | GetSetPropertyDescriptor<T>;
Union for reasonable configurations of property descriptors which could affect the type for the property.
type ValuePropertyDescriptor<T> = PropertyDescriptorFlags & {
get?: never;
set?: never;
value: T;
};
Partial property descriptor which contains a static value, instead of an accessor and/or mutator.
type WriteOnlyDescriptorsKeys<R> = R extends Record<infer K, TypedPropertyDescriptor<unknown>> ? {
[key in string & K]: IfWriteOnlyDescriptor<key, R[key]>;
}[string & K] : never;
Produce the non-mangled keys for the given property descriptors record which would produce write-only properties.
con: ConsoleLike
DQ: "\""
DURATION_DATE_DESIGNATORS: readonly DurationDesignator[]
DURATION_DESIGNATORS: readonly DurationDesignator[]
DURATION_KEY_BY_DESIGNATOR: Readonly<{
readonly Y: "year";
readonly D: "day";
readonly H: "hour";
readonly S: "second";
readonly W: "week";
}>
Map between DurationDesignator and Duration property name. Does not include M
, which is ambiguous, nor T
which does not correspond to a property.
DURATION_KEY_SECONDS: Readonly<Required<Omit<Duration, "month" | "text" | "year">>>
Lookup table for the conversion of a Duration property value to seconds. Does not include month
or year
, which have variable numbers of days.
DURATION_TIME_DESIGNATORS: readonly DurationDesignator[]
ecmaKeySort: Comparator<string>
Comparator for Object keys in ECMA "correct" order. Don't read the history on this. It will only depress you.
FILL_BATCHES = "fill"
Fill each batch to the maximum, except possibly the last. That is, if the list has 11 items with a maxPerBatch
of 5, you would get [5, 5, 1]
.
INDEX_KEY_PATTERN: RegExp
Pattern for an array index key, basically any integer.
INFINITY_SIGIL = "∞"
Text used for displaying human-readable infinity.
INT_SET_SIGIL = "ℤ"
intRange: IntRange
Start generating a range of integers.
JSON_PATH_ROOT: "$"
JSON_PUNCTUATION: readonly JsonPunctuation[]
JsonParseTransition: Readonly<{
readonly Begin: "begin";
readonly End: "end";
}>
JsonParseType: Readonly<{
readonly Arr: "array";
readonly Item: "item";
readonly Obj: "object";
readonly Prop: "property";
readonly Root: "root";
}>
JsonTokenType: Readonly<{
Boo: "boolean";
Nul: "null";
Num: "number";
Pun: "pun";
Spc: "space";
Str: "string";
}>
Discriminators for each of the type
values for JsonToken.
LCE_PRESET_NAMES: LCEPresetName[]
LCE_PRESETS: {
ansiC: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
width: number;
};
borlandC: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
width: number;
};
c88: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
};
c93: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
};
delphi: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
width: number;
};
glibc: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
seed: number | bigint | undefined;
width: number;
};
java: (seed?: number | bigint | undefined) => RNGOptions;
knuth: (seed: number | bigint | undefined) => {
a: bigint;
c: number;
m: bigint;
seed: number | bigint | undefined;
width: number;
};
visualC: (seed: number | bigint | undefined) => {
a: number;
c: number;
m: number;
floor: number;
seed: number | bigint | undefined;
width: number;
};
}
METRIC_PREFIXES: readonly string[]
List of metric prefixes, where the index is its base-1000 or base-1024 offset.
NEG_INFINITY_SIGIL = "-∞"
Text used for displaying human-readable negative infinity.
numberAsc: Comparator<number>
Numeric comparator which sorts lower values before higher ones.
numberDesc: Comparator<number>
Numeric (reverse) comparator which sorts higher values before lower ones.
PI_SIGIL = "π"
Text used for displaying human-readable pi.
REAL_SET_SIGIL = "ℝ"
SPREAD_BATCHES = "spread"
Try to spread out the batches evenly. That is, if the list has 11 items with a maxPerBatch
of 5, instead of getting [5, 5, 1]
you would get [4, 4, 3]
.
SQ: "'"
stringAsc: Comparator<string>
String comparator which sorts in lexicographic (dictionary) order.
stringDesc: Comparator<string>
String comparator which sorts in reverse lexicographic (dictionary) order.
SVG_ABSOLUTE_PATH_COMMANDS: readonly SvgAbsolutePathCommand[]
SVG_PATH_COMMANDS: readonly SvgPathCommand[]
SVG_RELATIVE_PATH_COMMANDS: readonly SvgRelativePathCommand[]
TIME_DELIMITERS: string[]
Possible delimiters between a date and a time value.