Skip to content

Instantly share code, notes, and snippets.

@webbower
Last active August 21, 2023 23:55
Show Gist options
  • Save webbower/1e6cecf3b91db9831eacd3d4f7bf18f3 to your computer and use it in GitHub Desktop.
Save webbower/1e6cecf3b91db9831eacd3d4f7bf18f3 to your computer and use it in GitHub Desktop.
Various simple utility types for improved codebase semantics
/**
* A function that converts one value of type A to another value or the same or a different type B
*
* Use with functions like:
* - @see Array.prototype.map()
* - `pipe()` or `compose()` functions
*/
export type Mapper<A = unknown, B = unknown> = (val: A) => B;
/**
* A function that takes a value of type V and returns true if the value meets some test criteria or
* false if not
*
* Use with functions like:
* - @see Array.prototype.filter()
* - @see Array.prototype.every()
* - @see Array.prototype.some().
*/
export type Predicate<V = unknown> = (val: V) => boolean;
/**
* A function that takes 2 values of the same type T and returns 1, 0, or -1 depending on the way
* they should be ordered.
*
* Use with functions like:
* - @see Array.prototype.sort().
*/
export type OrderComparator<T> = (a: T, b: T) => -1 | 0 | 1;
/**
* A function that takes a value of type V and returns an array of test failure data of type E (
* defaults to string type to assume simple failure string messages)
*/
export type Validator<F = string> = (val: unknown) => F[];
/**
* A function that takes zero or more arguments of any types and returns nothing
*
* Use with functions like:
* - @see EventTarget.prototype.addEventListener
* - @see EventEmitter.on
* - Any React native DOM components `on*` callback prop
* - @see setTimeout
* - @see setInterval
*/
export type Effectful = (...args: any[]) => void;
/**
* A function that takes a value of type R and a value of type V and returns a value that matches
* the type of the first arg.
*
* Use with functions like:
* - @see Array.prototype.reduce
* - Redux reducers
*/
export type Reducer<V, R> = (accumulator: R, current: V) => R;
/**
* A function that takes 2 args of the same type T and returns a value of the same type, usually to
* combine them.
*
* Use with functions like:
* - @see Array.prototype.reduce
*/
export type Concater<T> = (a: T, b: T) => T;
/**
* A function that takes one arg that is an ArrayLike of type T and a second arg of the same type T
* and returns a number from -1 to POSITIVE_INFINITY
*
* @todo Enable enforcement of return type to be >= -1 whenever TS allows for it
*
* Use with functions like:
* - @see Array.prototype.indexOf
* - @see String.prototype.search
*/
export type Locator<T> = (haystack: ArrayLike<T>, needle: T) => number;
/**
* A plain object with string keys and unknown property values
*/
export type PlainObject = Record<string, unknown>;
/**
* The value `{}`
*/
export type EmptyObject = Record<string, never>;
/**
* The value `[]`
*/
export type EmptyArray = [];
/**
* An array of zero or more entries of the same type T
*/
export type List<T> = T[];
/**
* An array of entries of the same type T with at least one entry
*/
export type NonEmptyList<T> = [T, ...T[]];
/**
* A value that is either null or undefined
*/
export type Nullish = null | undefined;
/**
* The empty value for the Boolean type
*/
export type EmptyBoolean = false;
/**
* The empty value for the String type
*/
export type EmptyString = '';
/**
* The empty value for the Number type
*/
export type EmptyNumber = 0;
/**
* A value that would be coerced to false in a boolean context
*/
export type Falsey = Nullish | EmptyBoolean | EmptyString | EmptyNumber;
/**
* The empty value for the base language types. All Falsey values plus empty array and empty object
*/
export type EmptyValue = Falsey | EmptyArray | EmptyObject;
/**
* An object with two keys:
* `concat` - a function that takes 2 args of type T and returns a value of the same type
* `empty` - a function that takes no args and returns a value of type T
*/
export type MonoidObject<T> = {
concat: Concater<T>;
empty: () => T;
};
/**
* A function that takes 2 args of type T and returns a value of the same type and has a property
* `empty` that is a function that takes no args and returns a value of type T
*/
export type MonoidFunction<T> = {
// Should be Concater<T> but TS doesn't seem to allow using a type alias for the function
// signature
(a: T, b: T): T;
empty: () => T;
};
/**
* Given the `typeof` a JS object or array/tuple const, return a union type of all the values of the object or array
*
* <code>
* // `MyEnum` can be used as a value or type
* const MyEnum = {
* ONE: 'one',
* TWO: 'two',
* THREE: 'three',
* } as const;
* type MyEnum = Values<typeof MyEnum>; // 'one' | 'two' | 'three'
*
* // `MyUnion` can be used as a value or type
* const MyUnion = ['one', 'two', 'three'] as const; // `as const` is required
* type MyUnion = Values<typeof MyUnion>; // 'one' | 'two' | 'three'
* </code>
*/
export type Values<T> = T extends Record<string, unknown> ? T[keyof T] : T extends readonly any[] ? T[number] : never;
/**
* Type for factory functions that define a default value for all keys and allow for partial overriding
*/
export type Factory<T> = (data?: Partial<T>) => T;
/**
* Converts an object type where all keys are made optional except those listed in RequiredKeys which become required
*
* <code>
* type MyProps = {
* prop1: string;
* prop2: number;
* prop3: string[];
* prop4: OtherType[];
* }
*
* type Modified = PartialExcept<MyProps, 'prop1' | 'prop3'>;
* // type Modified = {
* prop1: string;
* prop2?: number;
* prop3: string[];
* prop4?: OtherType[];
* // }
* </code>
*/
export type PartialExcept<T, RequiredKeys extends keyof T> = Partial<Omit<T, RequiredKeys>> &
{
[K in RequiredKeys]: T[K];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment