@nullndr/tsutils
v1.0.0
Published
Some utilities for TypeScript
Downloads
1
Readme
TypeScript utils
This packages contains some type
s 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 fine
In 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 work
Union
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; // error
Head
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 fine
This 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 }; // ok
ToUnion
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; // error
SimmetricDifference
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; // ok
Functions
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 is
nullor
undefined`.
assertNever
import { assertNever } from "@nullndr/tsutils";
assert
import { assert } from "@nullndr/tsutils";