@rickosborne/typical
TypeScript icon, indicating that this package has built-in type declarations

2025.3.12 • Public • Published

@rickosborne/typical

A collection of type definitions which I've found helpful across many projects.

Usage

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.

A quick note about file extensions

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 (via require) or .mjs (via import) 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's module, moduleResolution, and target settings.
  • Your package.json's type and imports settings.
  • An example of another package which imports correctly for you.

License

This package is licensed as CC-BY-NC-SA-4.0 unless otherwise noted. That is, Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.


API

Interfaces

JSONObject

export interface JSONObject extends Record<string, JSONSerializable> 

A record which contains only keys and values which can be serialized as JSON.

TypeAliases

AbstractConstructorLike

type AbstractConstructorLike<Params extends unknown[], Instance> = abstract new (...params: Params) => Instance;

AnyConstructorLike

type AnyConstructorLike<Params extends unknown[], Instance> = ConstructorLike<Params, Instance> | AbstractConstructorLike<Params, Instance>;

AnyFunction

type AnyFunction = (...params: any) => unknown;

Anything which could be called like a function.

AsyncRunnable

type AsyncRunnable = () => Promise<void | undefined>;

An async function which can be run without any input or output.

BiConsumer

type BiConsumer<T, U> = (t: T, u: U) => void;

Function which accepts the given input type without any output.

BinaryOperator

type BinaryOperator<T> = (left: T, right: T) => T;

Function which accepts two of the given type and returns the same.

BiPredicate

type BiPredicate<T, U> = (t: T, u: U) => boolean;

Function which evaluates two values against a condition.

BuiltIn

type BuiltIn = Date | Error | Function | Generator | {
    readonly [Symbol.toStringTag]: string;
} | RegExp;

Copied from ts-toolbox.

CombinedKeys

type CombinedKeys<T extends object, U extends object> = SpecificKeys<T> | SpecificKeys<U>;

All keys from both types, combined.

Comparator

type Comparator<T> = (a: T, b: T) => number;

A function which compares two values and returns the order in which they should be sorted. Negative values mean a should be sorted before b, while positive values mean the reverse. Zero means the two values are equivalent.

ConstructorLike

type ConstructorLike<Params extends unknown[], Instance> = new (...params: Params) => Instance;

A constructor-like value which, when invoked via new, accepts the given parameter type(s) and produces the given instance type.

ConstructorParams

type ConstructorParams<C> = C extends ConstructorLike<infer P, unknown> ? P : never;

Infer the types of the given constructor's parameters, in a tuple.

Consumer

type Consumer<T> = UnaryConsumer<T>;

Shorthand for UnaryConsumer.

DeepValued

type DeepValued<T> = T extends (infer U)[] ? DeepValued<U>[] : T extends object ? {
    [K in keyof T]: DeepValued<T[K]>;
} : NonNullable<T>;

Equivalent to a recursive Required.

Defined

type Defined<T> = T extends undefined ? never : T;

Filter out undefined from types. Equivalent to Exclude<T, undefined>.

Either

type Either<T extends object, U extends object> = Overwrite<NeverEvery<T>, U> | Overwrite<NeverEvery<U>, T>;

Produce a union of intersections, where all keys are present for both types, and can be used in destructuring assignments, but the individual property values are still mutually exclusive.

Equals

type Equals<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;

Type-level equality check. I did not come up with this. See this comment on the TypeScript issue for the source.

ExactlyOneOf

type ExactlyOneOf<T extends object> = {
    [K in keyof T]: {
        [One in K]: T[One];
    } & {
        [Other in keyof T as Other extends K ? never : Other]?: never;
    };
}[keyof T];

Given a record with some number of properties, fan out all permutations of that record where exactly 1 property is possible, while the rest are omitted.

FlagKeys

type FlagKeys<T extends object> = keyof {
    [K in keyof T as boolean extends T[K] ? K extends SpecificKeys<T> ? K : never : never]: K;
};

Extract only the keys for properties which could have Boolean values.

FunctionLike

type FunctionLike<Params extends unknown[], Return> = (...params: Params) => Return;

A function-like value which accepts the given parameter type(s) and produces the given return type.

FunctionParams

type FunctionParams<F> = F extends FunctionLike<infer P, unknown> ? P : never;

Infer the types of the given function's parameters, in a tuple.

IfEquals

type IfEquals<X, Y, Z> = Equals<X, Y> extends true ? Z : never;

If the first two parameters, X and Y, are equal, return the third, Z.

IfSpecificKeys

type IfSpecificKeys<T extends object> = SpecificKeys<T> extends never ? never : T;

If the object has any specific keys, return it.

IndexedPredicate

type IndexedPredicate<T> = (value: T, index: number) => boolean;

Function which evaluates a value and its position against a condition. Typically used for array or iterator filters.

ItemType

type ItemType<T extends unknown[] | Readonly<unknown[]>> = T extends (infer U)[] ? U : never;

Find the type of the items in an array.

JSONArray

type JSONArray = JSONSerializable[];

An array which contains only values which can be serialized as JSON.

JSONPrimitive

type JSONPrimitive = string | number | boolean | null;

A scalar literal value which can be serialized as JSON.

JSONSerializable

type JSONSerializable = JSONPrimitive | JSONObject | JSONArray;

Any value which can be serialized as JSON.

JSONSerializableOf

type JSONSerializableOf<T> = T extends JSONPrimitive ? T : T extends (infer U)[] ? JSONSerializableOf<U>[] : T extends undefined ? never : T extends object ? {
    [K in keyof T]: JSONSerializableOf<T[K]>;
} : never;

NeverEvery

type NeverEvery<T extends object> = {
    [K in keyof T as K extends SpecificKeys<T> ? K : never]?: never;
};

Map a type such that it has the same keys, but they all have never as their value type. Generally combined with Overwrite. Used when you want to acknowledge the possible presence of those properties, but you want to mask them out so they're never read or written in any meaningful way.

NonNull

type NonNull<T> = T extends null ? never : T;

Filter out null from types. Equivalent to Exclude<T, null>.

NoRecord

type NoRecord<T extends object> = object extends T ? Record<never, unknown> : {
    [K in keyof T as string extends K ? never : symbol extends K ? never : number extends K ? never : K]: T[K];
};

Remove the "wildcard" parts of an object, leaving only the concrete, specified parts. That is, it removes any keys which could be any string, any number, or any symbol.

NotEquals

type NotEquals<X, Y> = Equals<X, Y> extends true ? X : never;

If the parameters are not equal, return the first.

NotSame

type NotSame<X, Y> = X extends Y ? Y extends X ? never : X : never;

If the parameters are not the same, return the first.

OptionalKeys

type OptionalKeys<T extends object> = keyof {
    [K in keyof T as undefined extends T[K] ? K extends SpecificKeys<T> ? K : never : null extends T[K] ? K extends SpecificKeys<T> ? K : never : never]: K;
};

Extract only the keys for properties which could have undefined or null values.

Overwrite

type Overwrite<Loser extends object, Winner extends object> = Omit<Loser, keyof Winner & keyof Loser> & Winner;

Combine two types such that properties with matching keys are overwritten entirely by the Winner.

Predicate

type Predicate<T> = UnaryPredicate<T>;

Shorthand for UnaryPredicate.

ReadOnlyKeys

type ReadOnlyKeys<T extends object> = keyof {
    [K in keyof T as IfEquals<{
        readonly [key in K]: T[K];
    }, {
        [key in K]: T[K];
    }, K extends SpecificKeys<T> ? K : never>]: K;
};

Extract only the keys for properties which are read-only.

RequiredKeys

type RequiredKeys<T extends object> = keyof {
    [K in keyof T as undefined extends T[K] ? never : K extends SpecificKeys<T> ? K : never]: K;
};

Extract only the keys for properties which cannot have undefined or null values.

Resolve

type Resolve<T extends any, Seen = never> = T extends BuiltIn ? T : [T] extends [Seen] ? T : T extends any[] ? T extends Record<string | number | symbol, any>[] ? ({
    [K in keyof T[number]]: Resolve<T[number][K], T | Seen>;
} & unknown)[] : T : T extends readonly any[] ? T extends readonly Record<string | number | symbol, any>[] ? readonly ({
    [K in keyof T[number]]: Resolve<T[number][K], T | Seen>;
} & unknown)[] : T : {
    [K in keyof T]: Resolve<T[K], T | Seen>;
} & unknown;

Try to coerce tsc into showing an integrated type, instead of a type intersection / union / etc.

Runnable

type Runnable = () => (void | undefined);

A function which can be run without any input or output.

SharedKeys

type SharedKeys<T extends object, U extends object> = SpecificKeys<T> & SpecificKeys<U>;

Only the keys which exist in both types.

SpecificKey

type SpecificKey<K extends string | number | symbol> = K extends string ? string extends K ? never : K : K extends symbol ? symbol extends K ? never : K : K extends number ? number extends K ? never : K : never;

Eliminate catch-all keys from a union.

SpecificKeys

type SpecificKeys<T extends object> = T extends object ? object extends T ? never : SpecificKey<keyof T> : never;

Eliminate catch-all keys from an object.

Subtract

type Subtract<Left extends object, Right extends object> = Omit<Left, SharedKeys<Left, Right>>;

Remove all properties from the left type which have keys shared with the right type.

Supplier

type Supplier<T> = () => T;

Function which returns a given type without any input.

TriConsumer

type TriConsumer<T, U, V> = (t: T, u: U, v: V) => void;

Function which accepts the given input type without any output.

UnaryConsumer

type UnaryConsumer<T> = (value: T) => void;

Function which accepts the given input type without any output.

UnaryOperator

type UnaryOperator<T> = (value: T) => T;

Function which accepts the given type and returns the same.

UnaryPredicate

type UnaryPredicate<T> = (value: T) => boolean;

Function which evaluates a value against a condition.

Valued

type Valued<T> = T extends null | undefined ? never : T;

Filter out null and undefined from types. Equivalent to Exclude<T, null | undefined>.

WithOptionalProperty

type WithOptionalProperty<Original, Name extends string, Value> = Omit<Original, Name> & {
    [K in Name]?: Value;
};

Extend the given type with an optional property of the given name and value type. If the original type already had a property of that name, it is replaced not union-ed.

WithProperty

type WithProperty<Original, Name extends string, Value> = Omit<Original, Name> & {
    [K in Name]: Value;
};

Extend the given type with a property of the given name and value type. If the original type already had a property of that name, it is replaced not union-ed.

WithReadOnlyProperty

type WithReadOnlyProperty<Original, Name extends string, Value> = Omit<Original, Name> & {
    readonly [K in Name]: Value;
};

Extend the given type with a read-only property of the given name and value type. If the original type already had a property of that name, it is replaced not union-ed.

Variables

A_GT_B

A_GT_B = 1

Helper for comparators to make it clear to readers which value is greater-than the other.

A_LT_B

A_LT_B = -1

Helper for comparators to make it clear to readers which value is less-than the other.

EQ

EQ = 0

Helper for comparators to make it clear the two values are equivalent.

Package Sidebar

Install

npm i @rickosborne/typical

Weekly Downloads

9

Version

2025.3.12

License

CC-BY-NC-SA-4.0

Unpacked Size

70.9 kB

Total Files

122

Last publish

Collaborators

  • rickosborne