@nullndr/tsutils v1.0.0
TypeScript utils
This packages contains some types and function utilities for TypeScript.
types
functions
Types
CompErr
import type { CompErr } from "@nullndr/tsutils";Brand
import type { Brand } from "@nullndr/tsutils";TypeScript's type system is structural, meaning that any two types that are structurally equivalent are considered the same.
type Cat = { name: string };
type Dog = { name: string };
const petCat = (cat: Cat) => { console.log(cat.name); };
const pluto: Dog = { name: "Pluto" };
petCat(pluto); // works fineIn same case, you would like to simulate nominal typing inside TypeScript.
type Cat = { name: string };
type Dog = { name: string };
const petCat = (cat: Brand<Cat, "cat">) => { console.log(cat.name); };
const fido: Dog = { name: "fido" };
petCat(fido); // does not workUnion
import type { Union } from "@nullndr/tsutils";This is just a wrapper for the union | operator:
let u: Union<string, number> = "Hello";
u = 1;Intersetion
import type { Intersection } from "@nullndr/tsutils";For object this is just a wrapper for the intersection & operator:
type Bar = { bar: number };
type Foo = { foo: number };
let i: Intersection<Bar, Foo> = { bar: 1, foo: 1};For unions the type wraps Extract:
let i: Intersection<1 | 2 | 3, 2 | 3 | 4> = 2; // ok
i = 1; // error
i = 3; // ok
i = 4; // errorHead
import type { Head } from "@nullndr/tsutils";This type extracts the head type of a list or tuple:
type Tuple = [string, boolean, number];
let h: Head<Tuple> = "Hello";Tail
import type { Tail } from "@nullndr/tsutils";This type extracts the tail type of a tuple:
type Tuple = [string, boolean, number];
let t: Tail<Tuple> = [true, 0];IfAny
import type { IfAny } from "@nullndr/tsutils";With A, B and C types, assign B is A is any, C otherwise.
let a: IfAny<any, number, string> = 1;
let b: IfAny<number, number, string> = "Hello";IsAny
import type { IsAny } from "@nullndr/tsutils";Like IfAny but returns true if the type is any, false otherwise, usefull inside other types.
XOR
import type { XOR } from "@nullndr/tsutils";TypeScript's type system is structural, meaning that any two types that are structurally equivalent are considered the same.
This can lead to some unpleasant cases:
type A = {
a: 1;
};
type B = {
b: 2;
};
type C = A | B;
let a: C = { a: 1, b: 2 }; // works fineThis because { a: 1, b: 2} can be assigned both at A and B, in order to get really mutually exclusive use XOR:
type A = {
a: 1;
};
type B = {
b: 2;
};
let a: XOR<A, B> = { a: 1, b: 2 }; // error
a = { a: 1 }; // ok
a = { b: 2 }; // okToUnion
import type { ToUnion } from "@nullndr/tsutils";With an array, this type extracts the array's type:
let s: ToUnion<string[]> = "Hello";With a tuple, ToUnion creates an union with each element type inside the tuple:
let s: ToUnion<[string, number, boolean]> = "Hello"; // string | number | boolean
s = 1;
s = true;ToArray
import type { ToArray } from "@nullndr/tsutils";This type creates an array type from a given type:
let a: ToArray<number> = [0, 1, 2, 3, 4];Its behavior is the opposit of Flat<T>.
RemovePropsOf
import type { RemovePropsOf } from "@nullndr/tsutils";This type removes from an object all properties that are of a specific type.
type Foo = {
foo: number;
foobar: number;
bar: string;
}
let r: RemovePropsOf<Foo, number> = { bar: "Hello" };Overwrite
import type { Overwrite } from "@nullndr/tsutils";This type overwrites all properties of an source object which exist in a target object with the properties in the target object.
type Foo = {
foo: number;
bar: string;
}
type Bar = {
foo: string;
}
let o: Overwrite<Foo, Bar> = { foo: "Hello", bar: "World" };Difference
import type { Difference } from "@nullndr/tsutils";AwaitedReturnType
import type { AwaitedReturnType } from "@nullndr/tsutils";This type unwraps the awaited type of the return type of a function type.
async function foo(): Promise<number>;
let a: AwaitedReturnType<typeof foo> = 2;Filter
import type { Filter } from "@nullndr/tsutils";Flat
import type { Flat } from "@nullndr/tsutils";This type flats an array.
let f: Flat<string[]> = "Hello";Its behavior is the opposit of ToArray<T>
DeepFlat
import type { DeepFlat } from "@nullndr/tsutils";Like Flat<T> but recursively flats the result.
let f: DeepFlat<string[][][][]> = "Hello";Values
import type { Values } from "@nullndr/tsutils";Retrives a union of all property values in an object.
type Foo = {
a: string;
b: 1;
c: 2;
};
let v: Values<Foo> = "Hello"; // Ok
v = 1; // ok
v = 2; // ok
v = 3; // errorSimmetricDifference
import type { SimmetricDifference } from "@nullndr/tsutils";This type extracts the simmetric difference of two objects.
type Foo = {
foo: number;
foobar: string;
};
type Bar = {
bar: number;
foobar: string;
};
let s: SimmetricDifference<Foo, Bar> = { foo: 1, bar: 1};To get the simmetric difference of two unions, you can use Exclude<T, U> united with Exclude<U, T>.
type Foo = 1 | 2 | 3
type Bar = 2 | 4
type S = Exclude<Foo, Bar> | Exclude<Bar, Foo>
let a: S = 1; // ok
a = 2; // error
a = 3; // ok
a = 4; // okFunctions
assertDefined
import { assertDefined } from "@nullndr/tsutils";This function asserts that a given value is not null or undefined.
const user: User | null = await findUser(id);
assertDefined(user);
console.log(user.firstName);The function throws an 'AssertFailerror if the value isnullorundefined`.
assertNever
import { assertNever } from "@nullndr/tsutils";assert
import { assert } from "@nullndr/tsutils";