UNPKG

type-plus

Version:
1,357 lines (792 loc) โ€ข 37.4 kB
# type-plus [![NPM version][npm_image]][npm_url] [![NPM downloads][downloads_image]][npm_url] [![Release][github_release]][github_action_url] [![Codecov][codecov_image]][codecov_url] [![Visual Studio Code][vscode_image]][vscode_url] More than 200 type utilities for [TypeScript] for applications, library, and type-level programming. ## Table of Contents 1. [What's in the package?](#whats-in-the-package) 1. [Update organization](#update-organization) 2. [Update documentation](#update-documentation) 2. [Assertion Function](#assertion-function) 1. [assertType](#asserttype) 3. [Type Guard](#type-guard) 4. [Type Utilities](#type-utilities) 5. [Type Specific Utilities](#type-specific-utilities) 1. [any](#any) 2. [Array](#array) 3. [union](#union) 4. [bigint](#bigint) 5. [boolean](#boolean) 6. [function](#function) 7. [never](#never) 8. [null](#null) 9. [number](#number) 10. [numeric](#numeric) 11. [object](#object) 12. [Promise](#promise) 13. [string](#string) 14. [symbol](#symbol) 15. [tuple](#tuple) 16. [undefined](#undefined) 17. [unknown](#unknown) 18. [void](#void) 6. [Constant Types](#constant-types) 7. [JSON Support](#json-support) 8. [Type manipulation](#type-manipulation) 9. [Type Predicates](#type-predicates) 1. [Logical](#logical) 10. [Math](#math) 11. [Utility Functions](#utility-functions) 12. [Nominal Types](#nominal-types) 13. [Functional Types](#functional-types) 14. [Attribution](#attribution) 15. [Useful Tips](#useful-tips) 16. [Similar projects](#similar-projects) ## Installation ```sh npm install type-plus yarn add type-plus pnpm add type-plus ``` ## What's in the package? With over 200 types in [type-plus], it can become difficult to find the types you need. Also, some of the types need to be updated as TypeScript continue to evolve. Currently, we are updating [type-plus] with the following objective: - Update organization - Update documentation - Clean up and deprecate types - Upgrade TypeScript from 5.0.4 to 5.1 (potential breaking changes) ### Update organization Top-level exports of [type-plus] will contain types and functions that do not expect the input to be a specific type. For example, - `assertType()`, `isType()`, and `testType()` - Type filters and predicates such as `AnyType` or `IsArray` It can also have types and functions for specific types if it is a common convention, or the is no ambiguity, or for backwards compatibility purpose. Other type specific utilities will be added under their respective `*Plus` namespaces such as `ArrayPlus.At` or `NumberPlus.Positive`. ### Update documentation Each type and utility function in [type-plus] will be updated to include examples and tags to indicate its category and behavior. Each tag has an associated icon: - ๐Ÿ‘ฝ *alias*: Alias of another type - ๐Ÿšฆ *assertion*: assertion function - ๐Ÿ”ข *customizable*: the behavior of the type is customizable. - ๐Ÿ’€ *deprecated*: deprecated and will be removed soon - ๐ŸŒช๏ธ *filter*: a.k.a. *parse* These types perform some kind of test. If the input passes the test, the input is returned. Otherwise, it returns `never` - ๐Ÿ›ก๏ธ *guard*: type guard function - ๐Ÿ’ฅ *immediate*: the effect of the type can be observed immediately during development - ใŠ™๏ธ *internal*: the type is internal and should not be used directly - ๐Ÿƒ *runtime*: the function has runtime effect - ๐Ÿฉณ *shortcut*: Shortcut or convenient types - ๐Ÿงช *testing*: the type or function are designed for test - โš—๏ธ *transform*: these types transforms the input to another category - ๐Ÿฆด *utilities*: provide various functionalities - ๐ŸŽญ *validate*: a.k.a. *predicate* or *logical*. These types perform some kind of test. If the input passes the test, it returns `true` or `false` ## Assertion Function [Assertion Functions][assertion_functions] are special functions that asserts certain conditions of your program. It is introduced in TypeScript 3.7. They throw an error if the condition is not met, and return nothing otherwise. These assertion functions are typically used in runtime, so that that type of the value can be narrowed down. ### assertType [`assertType`](./ts/assertion/assert_type.ts) provides a generic assertion function, as well as many assertion functions for builtin types. > [`assertType<T>(subject)`](./ts/assertion/readme.md#asserttype) ๐Ÿ’€ deprecated. Use `assertType.as()` instead. `assertType<T>(subject, validator)`: ๐Ÿšฆ`assertion`: assert the `subject` is type `T` with the specified `validator`. If `subject` fails the assertion, a standard `TypeError` will be thrown and provide better error info. For example: ```ts const s: unknown = 1 // TypeError: subject fails to satisfy s => typeof s === 'boolean' assertType<boolean>(s, s => typeof s === 'boolean') ``` The message beautification is provided by [`tersify`](https://github.com/unional/tersify). > [`assertType.isUndefined()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `undefined`. > [`assertType.noUndefined()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `undefined`. > [`assertType.isNull()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `null`. > [`assertType.noNull()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `null`. > [`assertType.isNumber()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `number`. > [`assertType.noNumber()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `number`. > [`assertType.isBoolean()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `boolean`. > [`assertType.noBoolean()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `boolean`. > [`assertType.isTrue()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `true`. > [`assertType.noTrue()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `true`. > [`assertType.isFalse()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `false`. > [`assertType.noFalse()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `false`. > [`assertType.isString()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `string`. > [`assertType.noString()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `string`. > [`assertType.isFunction()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `function`. > [`assertType.noFunction()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not `function`. > [`assertType.isError()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is an `Error`. > [`assertType.noError()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is not an `Error`. > [`assertType.isConstructor()`](./ts/assertion/readme.md#asserttype) ๐Ÿ’€ deprecated. It does not work in all cases. It passes for function that can be called with `new`. If the subject is an arrow function, it can still return true after compilation. > [`assertType.isNever()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` is `never`. > [`assertType.custom()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: creates a custom assertion function. Using it to create a custom assertion function that provides better error messages. The message beautification is provided by [`tersify`](https://github.com/unional/tersify). > [`assertType.as<T>()`](./ts/assertion/readme.md#asserttype) ๐Ÿšฆ`assertion`: assert the `subject` as `T` without validator. This works similar to manual assertion `;(subject as T)` ## Type Guard [User-defined type guard functions][type_guard] is a function which its return type is specified as `x is T`. > [`isType()`](./ts/type-guard/readme.md#istype) ๐Ÿ›ก๏ธ `guard`: a generic type guard function > [`isType.t()`](./ts/type-guard/readme.md#istype) ๐Ÿ’€ `deprecated`: use `testType.true()` instead. > [`isType.f()`](./ts/type-guard/readme.md#istype) ๐Ÿ’€ `deprecated`: use `testType.false()` instead. > [`isType.never()`](./ts/type-guard/readme.md#istype) ๐Ÿ’€ `deprecated`: use `testType.never()` instead. > [`isType.equal()`](./ts/type-guard/readme.md#istype) ๐Ÿ’€ `deprecated`: use `testType.equal()` instead. ## Type Utilities > `Equal<A, B, Then = true, Else = false>` ๐Ÿ’€ deprecated. use `IsEqual` instead. This will be converted to a โ†ช๏ธ `parse`. > `IsEqual<A, B, Then = true, Else = false>` โญ• `predicate`: if `A` and `B` are the same. > `NotEqual<A, B, Then = true, Else = false>` ๐Ÿ’€ deprecated. use `IsNotEqual` instead. This will be converted to a โ†ช๏ธ `parse`. > `IsNotEqual<A, B, Then = true, Else = false>`: โญ• `predicate`: check if `A` and `B` are not the same. > `Extendable<A, B, Then = A, Else = never>` โ†ช๏ธ `parse`: check if `A` extends `B`. > `IsExtend<A, B, Then = true, Else = false>` โญ• `predicate`: check if `A` extends `B`. > `NotExtendable<A, B, Then = A, Else = never>`: โ†ช๏ธ `parse`: check if `A` not extends `B`. > `IsNotExtend<A, B, Then = true, Else = false>`: โญ• `predicate`: check if `A` not extends `B`. > `IsAssign<A, B, Then = true, Else = false>` ๐Ÿ’€ `deprecated`: use `CanAssign` instead. > `CanAssign<A, B, Then = true, Else = false>`: โญ• `predicate`: check can `A` assign to `B`. A typical usage is using it with `assertType`: ```ts assertType.isFalse(false as CanAssign<boolean, { a: string }>) assertType.isTrue(true as CanAssign<{ a:string, b:number }, { a: string }>) ``` > `StrictCanAssign<A, B, Then = true, Else = false>` โญ• `predicate`: can `A` strictly assign to `B` When `A` is a union, all branches must be assignable to `B`. ```ts StrictCanAssign<number | string, number> // false StrictCanAssign<number | string, number | string> // true ``` > `canAssign<T>(): (subject) => true` โญ•๐Ÿ’ป `predicate`, `compile-time` Returns a compile-time validating function to ensure `subject` is assignable to `T`. ```ts const isConfig = canAssign<{ a: string }>() assertType.isTrue(isConfig({ a: 'a' })) ``` > `canAssign<T>(false): (subject) => false`: โญ•๐Ÿ’ป `predicate`, `compile-time` Returns a compile-time validating function to ensure `subject` is not assignable to `T`. ```ts const notA = canAssign<{ a: string }>(false) assertType.isTrue(notA({ a: 1 })) notA({ a: '' }) // TypeScript complains ``` ## Type Specific Utilities [type-plus](./README.md) privides type checking utilities for every type. Each type has at least 4 type checks. Using `string` as an example, there are `StringType<T>`, `IsString<T>`, `NotStringType<T>`, and `IsNotString<T>`. Some types will have more checks, such as `boolean` has `StrictBooleanType<T>`, `TrueType<T>`, `FalseType<T>`. You can learn more in their respective sections: - [any](./ts/any/readme.md) - [array](./ts/array/readme.md) - [bigint](./ts/bigint/readme.md) - [boolean](./ts/boolean/readme.md) - [function](./ts/function/readme.md) - [never](./ts/never/readme.md) - [null](./ts/null/readme.md) - [number](./ts/number/readme.md) - [object](./ts/object/readme.md) - [string](./ts/string/readme.md) - [symbol](./ts/symbol/readme.md) - [tuple](./ts/tuple/readme.md) - [undefined](./ts/undefined/readme.md) - [unknown](./ts/unknown/readme.md) - [void](./ts/void/readme.md) - [mix types](./ts/mix-types/readme.md) ### [any](./ts/any/readme.md) - [`AnyType`](./ts/any/readme.md#anytype) - [`IsAny`](./ts/any/readme.md#isany) - [`NotAnyType`](./ts/any/readme.md#notanytype) - [`IsNotAny`](./ts/any/readme.md#isnotany) - [`AnyOrNeverType`](./ts/mix_types/readme.md#anyornevertype) - [`IsAnyOrNever`](./ts/mix_types/readme.md#isanyornever) ### [Array](./ts/array/readme.md) - ๐ŸŒช๏ธ[`ArrayType`](./ts/array/readme.md#arraytype): Filter `T` to ensure it is an array, excluding tuple. - ๐ŸŽญ[`IsArray`](./ts/array/readme.md#isarray): Validate that `T` is an array, excluding tuple. - ๐ŸŒช๏ธ[`NotArrayType`](./ts/array/readme.md#notarraytype): Filter `T` to ensure it is not an array, excluding tuple. - ๐ŸŽญ[`IsNotArrayType`](./ts/array/readme.md#isnotarraytype): Validate that `T` is not an array, excluding tuple. - ๐Ÿฆด[`At`](./ts/array/readme.md#at): Gets the type of the array or tuple at positive or negative index `N`. - ๐Ÿฆด๐Ÿ’€[`Concat`](./ts/array/readme.md#concat): Concats two arrays or tuples. - ๐Ÿฆด๐Ÿ”ข[`FindFirst`](./ts/array/readme.md#findfirst): Find the first type in the array or tuple `A` that matches `Criteria`. - [`FindLast`](./ts/array/readme.md#findlast) - [`Some`](./ts/array/readme.md#some) - โš—๏ธ[`Filter`](./ts/array/readme.md#filter): Filter the array or tuple `A`, keeping entries satisfying `Criteria`. - โš—๏ธ๐Ÿ‘ฝ[`KeepMatch`](./ts/array/readme.md#keepmatch): Keeps entries satisfying `Criteria` in array or tuple `A`. - ๐Ÿฆด๐Ÿ”ข[`Head`](./ts/array/readme.md#head): Gets the first entry in the tuple or the type of array `T`. - [`IntersectOfProps`](./ts/array/readme.md#intersectofprops) - [`MapToProp`](./ts/array/readme.md#maptoprop) - ๐Ÿฆด๐Ÿ”ข[`Last`](./ts/array/readme.md#last): Gets the last entry in the tuple or the type of array `T`. - [`literalArray`](./ts/array/readme.md#literalarray) - [`PadStart`](./ts/array/readme.md#padstart) - [`reduceWhile`](./ts/array/readme.md#reducewhile) - [`Reverse`](./ts/array/readme.md#reverse) - [`PropUnion`](./ts/array/readme.md#propunion) - [`UnionOfProps`](./ts/array/readme.md#unionofprops) - [`UnionOfValues`](./ts/array/readme.md#unionofvalues) - [`ArrayPlus.At`](./ts/array/readme.md#arrayplusat) - [`ArrayPlus.Concat`](./ts/array/readme.md#arrayplusconcat) - [`ArrayPlus.Entries`](./ts/array/readme.md#arrayplusentries) - ๐Ÿฆด๐Ÿ”ข[`ArrayPlus.Find`](./ts/array/readme.md#arrayplusfind): Finds the type in array `A` that matches `Criteria`. - [`ArrayPlus.FindLast`](./ts/array/readme.md#arrayplusfindlast) - [`ArrayPlus.Reverse`](./ts/array/readme.md#arrayplusreverse) - [`ArrayPlus.SplitAt`](./ts/array/readme.md#arrayplussplitat) - [`ArrayPlus.Some`](./ts/array/readme.md#arrayplussome) ### [union](./ts/union/readme.md) - [`IsUnion`](./ts/union//readme.md#isunion) - [`UnionType`](./ts/union/readme.md#uniontype) ### bigint > [`BigintType<T, Then = T, Else = never>`](./ts/bigint/bigint_type.ts#L15) โ†ช๏ธ `parse`: if `T` is `bigint` or bigint literal. > [`IsBigint<T, Then = true, Else = false>`](./ts/bigint/bigint_type.ts#L33) โญ• `predicate`: if `T` is `bigint` or bigint literal. > [`NotBigintType<T, Then = T, Else = never>`](./ts/bigint/bigint_type.ts#L47) โ†ช๏ธ `parse`: if `T` is not `bigint` or bigint literal. > [`IsNotBigInt<T, Then = true, Else = false>`](./ts/bigint/bigint_type.ts#L61) โญ• `predicate`: if `T` is not `bigint` or bigint literal. > [`StrictBigintType<T, Then = T, Else = never>`](./ts/bigint/strict_bigint_type.ts#L15) โ†ช๏ธ `parse`: if `T` is exactly `bigint`. > [`IsStrictBigint<T, Then = true, Else = false>`](./ts/bigint/strict_bigint_type.ts#L33) โญ• `predicate`: if `T` is exactly `bigint`. > [`NotStrictBigintType<T, Then = T, Else = never>`](./ts/bigint/strict_bigint_type.ts#L47) โ†ช๏ธ `parse`: if `T` is not exactly `bigint`. > [`IsNotStrictBigint<T, Then = true, Else = false>`](./ts/bigint/strict_bigint_type.ts#L61) โญ• `predicate`: if `T` is not exactly `bigint`. ### boolean > [`BooleanType<T>`](./ts/boolean/readme.md#type-checking) โ†ช๏ธ `parse`: `T === boolean`. > [`IsBoolean<T>`](./ts/boolean/readme.md#type-checking) โญ• `predicate`: `T === boolean` > [`NotBooleanType<T>`](./ts/boolean/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== boolean`. > [`IsNotBoolean<T>`](./ts/boolean/readme.md#type-checking) โญ• `predicate`: `T !== boolean` ### function > [`FunctionType<T>`](./ts/function/readme.md#type-checking) โ†ช๏ธ `parse`: `T === function`. > [`IsFunction<T>`](./ts/function/readme.md#type-checking) โญ• `predicate`: `T === function` > [`NotFunctionType<T>`](./ts/function/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== function`. > [`IsNotFunction<T>`](./ts/function/readme.md#type-checking) โญ• `predicate`: `T !== function` > `AnyFunction<P, R>` ๐Ÿ”จ `utilities`: a generic type for any function > `ExtractFunction<F>` ๐Ÿ”จ `utilities`: extract the function signature from a type `F`. > `extractFunction(fn: F)` ๐Ÿ”จ `utilities`: adjust type of `fn` to its function signature only. > `inspect<T>(value: T, inspector?: (v: T) => void)` ๐Ÿ”จ `utilities`: inspect a value and return it. Inspector defaults to `console.dir()` ### never > [`NeverType<T>`](./ts/never/readme.md#type-checking) โ†ช๏ธ `parse`: `T === never`. > [`IsNever<T>`](./ts/never/readme.md#type-checking) โญ• `predicate`: `T === never` > [`NotNeverType<T>`](./ts/never/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== never`. > [`IsNotNever<T>`](./ts/never/readme.md#type-checking) โญ• `predicate`: `T !== never` ### null > [`NullType<T>`](./ts/null/readme.md#type-checking) โ†ช๏ธ `parse`: `T === null`. > [`IsNull<T>`](./ts/null/readme.md#type-checking) โญ• `predicate`: `T === null` > [`NotNullType<T>`](./ts/null/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== null`. > [`IsNotNull<T>`](./ts/null/readme.md#type-checking) โญ• `predicate`: `T !== null` ### number > [`NumberType<T, Then = N, Else = never>`](./ts/number/number_type.ts#L14) โ†ช๏ธ `parse`: is the type `T` `number`. > [`IsNumber<T, Then = true, Else = false>`](./ts/number/number_type.ts#L27) โญ• `predicate`: is the type `T` `number`. > [`NotNumberType<T, Then = T, Else = never>`](./ts/number/number_type.ts#L40) โ†ช๏ธ `parse`: is the type `T` not `number`. > [`IsNotNumber<T, Then = true, Else = false>`](./ts/number/number_type.ts#L53) โญ• `predicate`: is the type `T` not `number`. > [`StrictNumberType<T, Then = N, Else = never>`](./ts/number/strict_number_type.ts#L19) โ†ช๏ธ `parse`: is the type `T` exactly `number`. > [`IsStrictNumber<T, Then = true, Else = false>`](./ts/number/strict_number_type.ts#L41) โญ• `predicate`: is the type `T` exactly `number`. > [`NotStrictNumberType<T, Then = T, Else = never>`](./ts/number/strict_number_type.ts#L55) โ†ช๏ธ `parse`: is the type `T` not exactly `number`. > [`IsNotStrictNumber<T, Then = true, Else = false>`](./ts/number/strict_number_type.ts#L69) โญ• `predicate`: is the type `T` not exactly `number`. ### numeric > [`Numeric`](./ts/numeric/numeric_type.ts#L4) ๐Ÿ“˜ `definition`: `number | bigint`. > [`Zero`](ts/numeric_plus/numeric_type.ts#L9) ๐Ÿ“˜ `definition`: `0 | 0n` > [`Integer<N, Then = N, Else = never>`](./ts/numeric/integer.ts#L15) โ†ช๏ธ `parse`: is integer. > [`IsInteger<N, Then = true, Else = false>`](./ts/numeric/integer.ts#L32) โญ• `predicate`: is integer. > [`NotInteger<N, Then = N, Else = never>`](./ts/numeric/integer.ts#L45) โ†ช๏ธ `parse`: is not integer. > [`IsNotInteger<N, Then = true, Else = false>`](./ts/numeric/integer.ts#L60) โญ• `predicate`: is not integer. > [`IsWhole<N, Then = true, Else = false>`](./ts/numeric/integer.ts#L75) ๐Ÿ’€โญ• `deprecated`, `predicate`: is integer. Use `IsInteger` instead. > [`Negative<N, Then = N, Else = never>`](./ts/numeric/negative.ts#L19) โ†ช๏ธ `parse`: is negative. > [`IsNegative<N, Then = true, Else = false>`](./ts/numeric/negative.ts#L53) โญ• `predicate`: is negative. > [`NonNegative<N, Then = N, Else = never>`](./ts/numeric/negative.ts#L69) โ†ช๏ธ `parse`: is not negative. > [`IsNonNegative<N, Then = N, Else = never>`](./ts/numeric/negative.ts#L101) โญ• `predicate`: is not negative. > [`Positive<N, Then = N, Else = never>`](./ts/numeric/positive.ts#15) โ†ช๏ธ `parse`: is positive. > [`IsPositive<N, Then = true, Else = false>`](./ts/numeric/positive.ts#L36) โญ• `predicate`: is positive. > [`NotPositive<N, Then = N, Else = never>`](./ts/numeric/positive.ts#48) โ†ช๏ธ `parse`: is not positive. > [`IsNotPositive<N, Then = true, Else = false>`](./ts/numeric/positive.ts#L60) โญ• `predicate`: is not positive. ### object > `filterKey()` ๐Ÿ”จ `utilities`: type adjusted filter by key. > `findKey()` ๐Ÿ”จ `utilities`: type adjusted find by key. > `forEachKey()` ๐Ÿ”จ `utilities`: type adjusted for each by key. > `HasKey<T, K>` ๐Ÿ”จ `utilities`: predicate type checking `T` has key `K`. > `hasKey()` ๐Ÿ”จ `utilities`: function of `HasKey`. > `IsRecord<T>` ๐Ÿ”จ `utilities`: `logical` predicate for `Record`. > `KeysWithDiffTypes<A, B>` ๐Ÿ”จ `utilities`: gets the keys common in `A` and `B` but with different value type. > `mapKey()` ๐Ÿ”จ `utilities`: type adjusted map by key. > `RecordValue<R>` ๐Ÿ”จ `utilities`: gets the value type `T`from `Record<any, T>` [video](https://www.youtube.com/watch?v=1J7xK6FUqPw). > `reduceByKey()` ๐Ÿ”จ `utilities`: type adjusted reduce by key. > `someKey()` ๐Ÿ”จ `utilities`: type adjusted some by key. > `SpreadRecord<A, B>` ๐Ÿ”จ `utilities`: type for `{...a, ...b}` when both `a` and `b` are `Record`\ for array, just do `[...A, ...B]`. ### Promise > `AwaitedProp<T, V>` ๐Ÿ”จ `utilities`: `Awaited` on specified props `P` in `T`. > `isPromise<R>(subject: any)` ๐Ÿ”จ `utilities`: `isPromise()` type guard. > `MaybePromise<T>` ๐Ÿ”จ `utilities`: Alias of `T | Promise<T>`. > `PromiseValue<P>` ๐Ÿ”จ `utilities`: Gets the type within the Promise. > `PromiseValueMerge<P1, P2, ...P9>` ๐Ÿ”จ `utilities`: Merge the values of multiple promises. > `mapSeries()` ๐Ÿ”จ `utilities`: Similar to `bluebird.mapSeries()` but works with `async`/`await`. > `transformMaybePromise(value, transformer)` ๐Ÿ”จ `utilities`: Apply the `transformer` to the `value`.\ It is also exported under `MaybePromise.transform()`. ### string > [`StringType<T>`](ts/string/readme.md#type-checking) โ†ช๏ธ `parse`: is `string`. > [`IsString<T>`](ts/string/readme.md#type-checking) โญ• `predicate`: is `string`. > [`NotStringType<T>`](ts/string/readme.md#type-checking) โ†ช๏ธ `parse`: is not `string`. > [`IsNotString<T>`](ts/string/readme.md#type-checking) โญ• `predicate`: is not `string`. ### symbol > [`SymbolType<T>`](ts/symbol/readme.md#type-checking) โ†ช๏ธ `parse`: is `symbol`. > [`IsSymbol<T>`](ts/symbol/readme.md#type-checking) โญ• `predicate`: is `symbol`. > [`NotSymbolType<T>`](ts/symbol/readme.md#type-checking) โ†ช๏ธ `parse`: is not `symbol`. > [`IsNotSymbol<T>`](ts/symbol/readme.md#type-checking) โญ• `predicate`: is not `symbol`. ### tuple - ๐ŸŒช๏ธ [`TupleType`](./ts/tuple/readme.md#tupletype): Filter `T` to ensure it is a tuple, excluding array. - ๐ŸŽญ [`IsTuple`](./ts/tuple/readme.md#istuple): Validate that `T` is a tuple, excluding array. - ๐ŸŒช๏ธ [`NotTupleType`](./ts/tuple/readme.md#nottupletype): Filter `T` to ensure it is not an tuple, excluding array. - ๐ŸŽญ [`IsNotTuple`](./ts/tuple/readme.md#isnottupletype): Validate that `T` is not an tuple, excluding array. - โš—๏ธ๐Ÿ”ข[`CommonPropKeys`](./ts/tuple/readme.md#commonpropkeys): Gets the common property keys of the elements in tuple `T`. - โš—๏ธ๐Ÿ’€`CommonKeys`: Deprecated. Please use `CommonPropKeys` instead. - โš—๏ธ๐Ÿ”ข[`DropFirst`](./ts/tuple/readme.md#dropfirst): Drops the first entry in the tuple`T`. - โš—๏ธ๐Ÿ”ข[`DropLast`](./ts/tuple/readme.md#droplast): Drops the last entry in the tuple`T`. > `CreateTuple<L, T>` ๐Ÿ”จ `utilities`: creates `tuple<T>` with `L` number of elements. > `drop(array, value)` ๐Ÿ”จ `utilities`: drop a particular value from an array. > `DropMatch<A, Criteria>` ๐Ÿ”จ `utilities`: drops entries matching `Criteria` in array or tuple `A`. > `DropUndefined<A>` ๐Ÿ”จ `utilities`: drop undefined entries from array of tuple `A`. ### undefined > [`UndefinedType<T>`](./ts/undefined/readme.md#type-checking) โ†ช๏ธ `parse`: `T === undefined`. > [`IsUndefined<T>`](./ts/undefined/readme.md#type-checking) โญ• `predicate`: `T === undefined` > [`NotUndefinedType<T>`](./ts/undefined/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== undefined`. > [`IsNotUndefined<T>`](./ts/undefined/readme.md#type-checking) โญ• `predicate`: `T !== undefined` ### unknown > [`UnknownType<T>`](./ts/unknown/readme.md#type-checking) โ†ช๏ธ `parse`: `T === unknown`. > [`IsUnknown<T>`](./ts/unknown/readme.md#type-checking) โญ• `predicate`: `T === unknown` > [`NotUnknownType<T>`](./ts/unknown/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== unknown`. > [`IsNotUnknown<T>`](./ts/unknown/readme.md#type-checking) โญ• `predicate`: `T !== unknown` ### void > [`VoidType<T>`](./ts/void/readme.md#type-checking) โ†ช๏ธ `parse`: `T === void`. > [`IsVoid<T>`](./ts/void/readme.md#type-checking) โญ• `predicate`: `T === void` > [`NotVoidType<T>`](./ts/void/readme.md#type-checking) โ†ช๏ธ `parse`: `T !== void`. > [`IsNotVoid<T>`](./ts/void/readme.md#type-checking) โญ• `predicate`: `T !== void` ## Constant Types > `KeyTypes` ๐Ÿ“˜ `definition`: type of all keys. > `PrimitiveTypes` ๐Ÿ“˜ `definition`: all primitive types, including `Function`, `symbol`, and `bigint`. > `ComposableTypes` ๐Ÿ“˜ `definition`: Types that can contain custom properties. i.e. `object`, `array`, `function`. > `NonComposableTypes` ๐Ÿ“˜ `definition`: Types that cannot contain custom properties. i.e. not composable. ## JSON Support > `JSONPrimitive` ๐Ÿ“˜ `definition`: primitive types valid in JSON > `JSONObject` ๐Ÿ“˜ `definition`: JSON object > `JSONArray` ๐Ÿ“˜ `definition`: JSON array > `JSONTypes` ๐Ÿ“˜ `definition`: all JSON compatible types. > `JSONTypes.get<T>(obj, ...props)` ๐Ÿ”จ `utilities`: get a cast value in JSON ```ts import { JSONTypes } from 'type-plus' const someJson: JSONTypes = { a: { b: ['z', { c: 'miku' }]}} JSONTypes.get<string>(someJson, 'a', 'b', 1, 'c') // miku ``` ## Type manipulation > `ANotB<A, B>` ๐Ÿ”จ `utilities`: get object with properties in `A` and not in `B`, including properties with a different value type. > `BNotA<A, B>` ๐Ÿ”จ `utilities`: flip of `ANotB` > `as<T>(subject)` ๐Ÿ”จ `utilities`: assert `subject` as `T`. Avoid ASI issues such as `;(x as T).abc` > `asAny(subject)` ๐Ÿ”จ `utilities`: assert `subject` as `any`. Avoid ASI issue such as `;(x as any).abc` > `EitherAnd<A, B, [C, D]>` ๐Ÿ’€๐Ÿ”จ `deprecated`,`utilities`: Renamed to `EitherOrBoth`. combines 2 to 4 types as `A | B | (A & B)`. This is useful for combining options. > `EitherOrBoth<A, B, [C, D]>` ๐Ÿ”จ `utilities`: combines 2 to 4 types as `A | B | (A & B)`. This is useful for combining options [video](https://youtu.be/jBxx03NT4Ik). > `Except<T, K>` ๐Ÿ’€๐Ÿ”จ `deprecated`,`utilities`: same as `Omit<T, K>`. > `ExcludePropType<T, U>` ๐Ÿ”จ `utilities`: excludes type `U` from properties in `T`. > `KeyofOptional<T>` ๐Ÿ”จ `utilities`: `keyof` that works with `Record<any, any> | undefined`. > `KnownKeys<T>` ๐Ÿ”จ `utilities`: extract known (defined) keys from type `T`. > `LeftJoin<A, B>` ๐Ÿ”จ `utilities`: left join `A` with `B` > `NonNull<T>` ๐Ÿ”จ `utilities`: remove `null` > `NonNullable<T>` (built-in) ๐Ÿ”จ `utilities`: adjust the type not to nullable > `NonUndefined<T>` ๐Ÿ”จ `utilities`: remove `undefined` > `Omit<T, K>` ๐Ÿ”จ `utilities`: From `T`, pick a set of properties whose keys are not in the union `K`. This is the opposite of `Pick<T, K>`. > `OptionalKeys<T>` ๐Ÿ”จ `utilities`: gets keys of optional properties in `T`. > `PartialExcept<T, U>` ๐Ÿ’€๐Ÿ”จ `deprecated`,`utilities`: same as `PartialOmit<T, U>`. > `PartialOmit<T, U>` ๐Ÿ”จ `utilities`: makes the properties not specified in `U` becomes optional. > `PartialPick<T, U>` ๐Ÿ”จ `utilities`: makes the properties specified in `U` becomes optional. > `Pick<T, K>` ๐Ÿ”จ `utilities`: pick properties `K` from `T`. Works with unions. > `RecursivePartial<T>` ๐Ÿ”จ `utilities`: make type `T` optional recursively. > `RecursiveRequired<T>` ๐Ÿ”จ `utilities`: make type `T` required recursively. > `ReplaceProperty<T, K, V>` ๐Ÿ”จ `utilities`: replace property `K` in `T` with `V`. > `RequiredKeys<T>` ๐Ÿ”จ `utilities`: gets keys of required properties in `T`. > `RequiredPick<T, U>` ๐Ÿ”จ `utilities`: makes the properties specified in `U` become required. > `RequiredExcept<T, U>` ๐Ÿ”จ `utilities`: makes the properties not specified in `U` become required. > `RecursiveIntersect<T, U>` ๐Ÿ”จ `utilities`: intersect type `U` onto `T` recursively. > `ValueOf<T>` ๐Ÿ”จ `utilities`: type of the value of the properties of `T`. > `Widen<T>` ๐Ÿ”จ `utilities`: widen literal types. PropType ๐Ÿ’€ ...no helper type for this. Just do `YourType['propName']`. ## Type Predicates Type predicates are type alias that returns `true` or `false`. They can be used to compose complex types. > `HasKey<T, K>` ๐Ÿ”จ `utilities`: predicate type checking `T` has key `K`. > `IsAny<T>` ๐Ÿ”จ `utilities`: `T === any` (updated to impl: [expect-type]). > `IsBoolean<T>` ๐Ÿ”จ `utilities`: check for `boolean`, but not for `true` nor `false`. > `IsDisjoint<A, B>` ๐Ÿ”จ `utilities`: is `A` and `B` is a disjoint set. > `IsEmptyObject<T>` ๐Ÿ”จ `utilities`: is `T === {}`. > `IsLiteral<T>` ๐Ÿ”จ `utilities`: is `T` a literal type (literal string or number). ### Logical > `If<Condition, Then = true, Else = false>` ๐Ÿ”จ `utilities`: if statement > `And<A, B, Then = true, Else = false>` ๐Ÿ”จ `utilities`: logical `AND` > `Or<A, B, Then = true, Else = false>` ๐Ÿ”จ `utilities`: logical `OR` > `Xor<A, B, Then = true, Else = false>` ๐Ÿ”จ `utilities`: logical `XOR` > `Not<X, Then = true, Else = false>` ๐Ÿ”จ `utilities`: logical `NOT` Note that these types work correctly with the `boolean` type. e.g.: ```ts type R = And<boolean, true> // boolean type R = Not<boolean> // boolean` ``` There is a problem with generic distribution: <https://github.com/microsoft/TypeScript/issues/41053> So you may encounter some weird behavior if your logic is complex. ## Math The math types in `type-plus` works with most numeric types. It works with `number` and `bigint`, positive and negative number, including floating point numbers. It will cast the type between `number` and `bigint` if needed. > `Abs<N, Fail = never>` ๐Ÿ”จ `utilities`: `Abs(N)`. > `Max<A, B, Fail = never>` ๐Ÿ”จ `utilities`: `max(A, B)` > `GreaterThan<A, B>` ๐Ÿ”จ `utilities`: `A > B`. > `Add<A, B>` ๐Ÿ”จ `utilities`: `A + B`. > `Subtract<A, B>` ๐Ÿ”จ `utilities`: `A > B`. > `Increment<A>` ๐Ÿ”จ `utilities`: alias of `Add<A, 1>`. > `Decrement<A>` ๐Ÿ”จ `utilities`: alias of `Subtract<A, 1>`. > `Multiply<A, B` ๐Ÿ”จ `utilities`: `A * B`. ## Utility Functions > `amend(subject)...` ๐Ÿ”จ `utilities`: amend subject as union or intersect of `T`. > `facade(subject, ...props)` ๐Ÿ”จ `utilities`: create a facade of `subject`. > `getField(subject, key, defaultValue)` ๐Ÿ”จ `utilities`: get a field from a subject. Works against nullable and optional subject. > `hasKey()` ๐Ÿ”จ `utilities`: function of `HasKey`. > `hasProperty(value, prop)` ๐Ÿ”จ `utilities`: assert `value` has property `prop`. This will pick the correct union type. > `isConstructor(subject)` ๐Ÿ”จ `utilities`: type guard `subject` is a constructor. > `isSystemError(code, err)` ๐Ÿ”จ `utilities`: type guard `err` with NodeJS error code. > `omit(obj, ...props)` ๐Ÿ”จ `utilities`: omit properties from `obj`. > `pick(obj, ...props)` ๐Ÿ”จ `utilities`: pick properties from `obj`. > `record<K, V>(value?)` ๐Ÿ”จ `utilities`: create a `Record<K, V>` without extra object prototype. > `record<R>(value?)` ๐Ÿ”จ `utilities`: create a record `R` (e.g. `{ a: number }`) without extra object prototype. > `required(...)` ๐Ÿ”จ `utilities`: merge options and remove `Partial<T>`. From [`unpartial`](https://github.com/unional/unpartial) > `requiredDeep(...)` ๐Ÿ”จ `utilities`: merge options deeply and remove `Partial<T>`. From [`unpartial`](https://github.com/unional/unpartial) > `split(target, ...splitters)` ๐Ÿ”จ `utilities`: split one object into multiple objects. > `stub<T>(value)` ๐Ÿ”จ `utilities`: stub a particular type `T`. > `stub.build<T>(init?)` ๐Ÿ”จ `utilities`: build a stub for particular type `T`. > `typeOverrideIncompatible<T>()` ๐Ÿ”จ `utilities`: override only the incompatible portion between two types. ```ts type A = { foo: boolean, bar: string, baz: string } const overrider = typeOverrideIncompatible<A>() const source = { foo: 1, bar: 'bar', baz: 'baz' } // only the `foo` property is available to override. overrider(source, { foo: !!source.foo }) ``` > `unpartial()` ๐Ÿ”จ `utilities`: merge options and remove `Partial<T>` values. From [`unpartial`](https://github.com/unional/unpartial) > `context()` ๐Ÿ”จ `utilities`: a context builder. This is useful to build context for functional programming. It is a sync version of the `AsyncContext` from [async-fp](https://unional/async-fp). ```ts import { context } from 'type-plus' // { a: 1, b: 2 } const ctx = context({ a: 1 }) .extend(c => ({ b: c.a + 1 })) .build() ``` ## Nominal Types The TypeScript type system is structural. In some cases, we want to express a type with nominal behavior. `type-plus` provides two kinds of nominal types: `Brand` and `Flavor`. `Brand<B, T>`: `brand(type, subject?)`: Branded nominal type is the stronger nominal type of the two. It disallows unbranded type assigned to it: ```ts const a = brand('a', { a: 1 }) const b = { a: 1 } a = b // error ``` `subject` can be any type, from primitive to strings to objects. `brand(type)`: If you do not provide `subject`, `brand(type)` will return a brand creator, so that you can use it to create multiple branded values: ```ts const nike = brand('nike') const shirt = nike('shirt') const socks = nike('socks') ``` `Flavor<F, T>`: `flavor(type, subject?)`: The key difference between `Flavor` and `Brand` is that unflavored type can be assigned to `Flavor`: ```ts let f = flavor('orange', 'soda') f = 'mist' // ok ``` Also, `Brand` of the same name can be assigned to `Flavor`, but `Flavor` of the same name cannot be assigned to `Brand`. `nominalMatch(a, b)`: ๐Ÿ”จ `utilities`: compare if the two values are nominally equal. Works with both `Brand` and `Flavor`. ```ts const b1 = brand('x', 1) const b2 = brand('y', 1) nominalMatch(b1, b2) // false ``` ## Functional Types > `ChainFn<T>: T` ๐Ÿ”จ `utilities`: chain function that returns the input type. > `compose(...fns): F` ๐Ÿ”จ `utilities`: compose functions ## Attribution Some code in this library is created by other people in the TypeScript community. I'm merely adding them in and maybe making some adjustments. Whenever possible, I add attribution to the person who created those **codes** in the file. ## Useful Tips > <https://github.com/microsoft/TypeScript/wiki/Performance> ## Similar projects - [expect-type]: Compile-time tests for types - [hotscript]: Higher-order TypeScript - [spec.ts]: write tests for your types! - [ts-calc]: compute with typescript type system, part of [hotscript] - [ts-essentials]: all essential TypeScript types in one place. - [ts-expect]: Checks values in TypeScript match expectations. - [ts-toolbelt]: TypeScript's largest utility library. - [type-fest]: a collection of essential TypeScript types. - [type-zoo]: a modest type lib usable today. - [typepark]: a new type collection offering tuple manipulation and `Pipe`. - [typelevel-ts]: a type lib by [@gcanti], author of several FP libraries in TS. - [typical]: a playground of type-level operations for TypeScript. - [utility-types]: collection of utility types, complementing TypeScript build-in mapped types ans aliases. - [earl]: Ergonomic, modern and type-safe assertion library for TypeScript [@gcanti]: https://github.com/gcanti [codecov_image]: https://codecov.io/gh/unional/type-plus/branch/master/graph/badge.svg [codecov_url]: https://codecov.io/gh/unional/type-plus [downloads_image]: https://img.shields.io/npm/dm/type-plus.svg?style=flat [earl]: https://github.com/l2beat/earl [expect-type]: https://github.com/mmkal/expect-type [github_action_url]: https://github.com/unional/type-plus/actions [github_release]: https://github.com/unional/type-plus/workflows/release/badge.svg [hotscript]: https://github.com/gvergnaud/hotscript [npm_image]: https://img.shields.io/npm/v/type-plus.svg?style=flat [npm_url]: https://npmjs.org/package/type-plus [spec.ts]: https://github.com/aleclarson/spec.ts [ts-calc]: https://github.com/ecyrbe/ts-calc [ts-essentials]: https://github.com/ts-essentials/ts-essentials [ts-expect]: https://github.com/TypeStrong/ts-expect [ts-toolbelt]: https://github.com/millsp/ts-toolbelt [type-fest]: https://github.com/sindresorhus/type-fest [type-plus]: https://github.com/unional/type-plus [type-zoo]: https://github.com/pelotom/type-zoo [typelevel-ts]: https://github.com/gcanti/typelevel-ts [typepark]: https://github.com/kgtkr/typepark [TypeScript]: https://www.typescriptlang.org [typical]: https://github.com/KiaraGrouwstra/typical [utility-types]: https://github.com/piotrwitek/utility-types [vscode_image]: https://img.shields.io/badge/vscode-ready-green.svg [vscode_url]: https://code.visualstudio.com/ [assertion_functions]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions [type_guard]: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates