# What is tsafe?

Powerful TypeScript features like [assertion functions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions) or [user-defined type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) are only useful if paired with utility functions.

TypeScript, however, only exports type helpers (e.g. `Record`, `ReturnType`, etc.).

This module provides *«the missing builtins»* such as [the assert function](https://docs.tsafe.dev/assert) and other utilities that cannot be just type helpers.

{% hint style="info" %}
`tsafe` is both an [NPM](https://www.npmjs.com/package/tsafe) and a [Deno](https://deno.land/x/tsafe) module. *(Achieved with* [*denoify*](https://denoify.land)*)*
{% endhint %}


# How to import

Recommended way to import tsafe

### Node / Browser

```typescript
import { assert, type Equals, typeGuard } from "tsafe";
// NOTE: You can also cherry pick imports, example: 
// import { assert, is, type Equals } from "tsafe/assert";
// import { typeGuard } from "tsafe/typeGuard";
// But if you are in ESM environement it's unessesary. 
// Even if you import from the index your bundler will three shake
// and include only the utility that you use.
```

### Deno

`/deps.ts`

```typescript
export { assert, type Equals } from "https://deno.land/x/tsafe@v0.7.3/mod.ts";
```

```typescript
import { assert, type Equals } from "./deps.ts";
```


# assert

```typescript
import { assert } from "tsafe/assert";

declare const x: number | string;

assert(typeof x === "string");

x.toLowerCase(); //<= Here TypeScript knows that x is a string
```

The classic assert function, it takes a value as input, if the value is falsy it throws or else it does nothing. Functionally it can be summed up to this:

```typescript
function assert(condition) {
	if (!condition) {
		throw new Error();
	}
}
```

Typewise however, it takes advantage of the asserts condition statement. If you pass a [type guard](https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types) as value TypeScript can make inference on what happens after the `assert` instruction.

## Assertion on types

Assert can also be used to confirm assertion on types.

You can for example test if a type extends another by doing:

```typescript
import { assert } from "tsafe/assert";

type A = "foo" | "bar";
type B = "foo" | "bar" | "baz";

//You will get red squiggly lines if A does not extend B
assert<A extends B ? true : false>;
```

The main usecase `assert<Equals<A, B>>`:

{% content-ref url="/pages/-MkXjMdFv9FjdGeD7zIJ" %}
[Equals](/equals)
{% endcontent-ref %}

## assert + is

{% content-ref url="/pages/-M\_Yb\_bq2pI7FrHcQr98" %}
[is](/is)
{% endcontent-ref %}

## Error thrown

When the value is falsy assert throws an instance of `AssertionError`. Assertion error, extends Error and can be imported like this:

```typescript
import { AssertionError } from "tsafe/assert";
```

A specific error message can be passed as second argument to the assert function.

```typescript
import { assert, AssertionError } from "tsafe/assert";

try {
	assert(false, "foo bar baz");
} catch (error) {
	console.log(error instanceof AssertionError); // true
	console.log(error.message); // Wrong assertion encountered: "foo bar baz"
	// Access the original message
	console.log(error.originalMessage); // foo bar baz
}
```

The message can be a string or callback that returns a string. This is useful when the message is costly to create.

```typescript
import { assert, AssertionError } from "tsafe/assert";

let called = false;
const getMessage = () => {
	// Do some expensive logic
	called = true;
	return "foo bar baz"
}

try {
	assert(true, getMessage)
	console.log(called) // false, getMessage has not been called yet
	assert(false, getMessage);
} catch (error) {
	console.log(called) // true, getMessage has been called
	console.log(error instanceof AssertionError); // true
	console.log(error.message); // Wrong assertion encountered: "foo bar baz"
}
```


# Equals

Let you test if two types are the same

### Type level  testing

<figure><img src="/files/0wg7WFjpTwZmaJK2YpFr" alt=""><figcaption></figcaption></figure>

[Playground](https://stackblitz.com/edit/typescript-rfpzav?file=index.ts\&view=editor)

A less trivial example: [The code](https://github.com/codegouvfr/react-dsfr/blob/main/src/lib/spacing.ts) and it's [corresponding test file](https://github.com/codegouvfr/react-dsfr/blob/main/test/types/spacing.ts).

{% hint style="info" %}
If you are writing tests for your type, you definitely want to checkout [`//@ts-expect-error`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments)
{% endhint %}

### Making sure that a zod schema validates a given type

<figure><img src="/files/F77SlhjnUlz168gmj0st" alt=""><figcaption></figcaption></figure>

[Playground](https://stackblitz.com/edit/typescript-eheop6?file=index.ts\&view=editor)

```typescript

import { z } from "zod";
import { assert, type Equals } from "tsafe/assert";
import { id } from "tsafe/id";

type Xyz= // ...

const zXyz = (()=>{

   type TargetType = Xyz;
   
   const zTargetType = z.;
   
   type InferredType = z.infer<typeof zTargetType>;
   
   assert<Equals<TargetType, InferredType>>;
   
   return id<z.ZodType<TargetType>>(zTargetType);   

})();
```

### Making sure all cases of a switch are dealt with

<figure><img src="/files/BB3DQR8VzDXjJgDXzgVc" alt=""><figcaption></figcaption></figure>

[Playground](https://stackblitz.com/edit/typescript-ryj2ba?file=index.ts\&view=editor)


# id

The identity function

Literally just:

```typescript
export const id = <T>(x: T) => x;
```

It directly returns the parameter it was given as input.

## Example 1: Simultaneously declaring a type and instantiating a default value for this type

```typescript
import { id } from "tsafe/id";

const defaultCat = {
	name: "Felix",
	gender: id<"male" | "female">("male"),
};

type Cat = typeof defaultCat;
```

![Cat\["gender"\] is "male" | "female"](/files/-M_HBMeFPs9A_CwsCpDA)

If we don't use `id`, `Cat["gender"]` is of type `string`

![Cat\["gender"\] is string](/files/-M_HCRa0l6xqVPUT8WdG)

We could have used `"male" as "male" | "female"`

```typescript
const defaultCat = {
	name: "Felix",
	gender: "male" as "male" | "female",
};

type Cat = typeof defaultCat;
```

But this is less type safe because we do not validate that the value that we gives to gender is actually assignable to "male" | "female".

This error for example slips through:

!["MALE" is all caps, which should be a typing error](/files/-M_HE-wpMZBjlTwDEPtl)

## Example 2: Instantiating an object of type T

Let's say you have this function:

```typescript
declare function getArea(shape: Shape): number;
```

And let's say a shape object is defined as follows:

```typescript
type Circle = { type: "circle"; radius: number };
type Square = { type: "square"; sideLength: number };
type Shape = Circle | Square;
```

We want to instantiate a `Circle` and pass it to `getArea` we can do:

```typescript
const circle: Circle = { type: "circle", radius: 33 };
getArea(circle);
```

If we want to avoid declaring a variable, we can do

```typescript
getArea({ type: "circle", radius: 33 });
```

The problem, however, is that this `Circle` was not as easy to instantiate because TypeScript doesn’t know what kind of shape we are trying to instantiate:

![Every possible properties are listed](/files/-M_H2tt2Vgu3xQa04ezL)

id lets you declare that the shape you are instantiating is a `Circle`

```typescript
import { id } from "tsafe/id";

getArea(id<Circle>({ type: "circle", radius: 33 }));
```

![TypeScript knows we are instantiating a Circle](/files/-M_H5_VFU4s5qgm-9Acv)


# is

`is` is meant to be used in conjunction with assert and enable you to tell the compiler:

"*Trust me this `value` is of type `T`"* or "*Trust me this `value` is not of type `T`*"

![](https://user-images.githubusercontent.com/6702424/118082020-c2e5dd80-b3bc-11eb-9ea9-71fa8206f704.gif)

```typescript
import { assert, is } from "tsafe/assert";

type Circle = { radius: number };
type Square = { sideLength: number };
type Shape = Circle | Square;

declare const shape: Shape;

//You: Trust me TypeScript, I know that shape is a Circle.
assert(is<Circle>(shape));

//TypeScript: Ok if you say so...it has a radius then.
shape.radius;
```

Equally useful you can tell TypeScript that your shape is not a `Square`, it will infer that, it is then a `Circle`.

```typescript
//You: Trust me TypeScript, I know that shape is not a Square.
assert(!is<Square>(shape));

//TypeScript: Ok so by elimination it should be a Circle!
shape.radius;
```

{% hint style="danger" %}
`is` must **always** be used in conjunction with [`assert`](/assert) as described in the example above.

You aren't even allowed to do something like `assert(is<Circle>(shape) && shape.radius > 100 )`

For any other use case consider[`typeGuard`](/typeguard) instead.
{% endhint %}

{% hint style="warning" %}
It is important to understand that here that when you run the instruction `assert(typeGuard<Circle>(shape))` if the shape happens not to be a Circle you won't get an error at runtime.
{% endhint %}


# objectKeys

Like Object.keys() but with a better return type

Functionally identical to `Object.keys()` except that the return type ain't just `string` but a typed array.

```typescript
import { assert, type Equals } from "tsafe/assert";
import { objectKeys } from "tsafe/objectKeys";

const obj = {
	a: 1,
	b: "ok",
	c: null,
};

//    v keys is an array of "a", "b", "c"
const keys = objectKeys({
	a: 1,
	b: 2,
	c: 3,
});

assert<Equals<typeof keys, ("a" | "b" | "c")[]>>();
```

{% hint style="warning" %}
WARNING: Only use with object you have instantiated yourself. Some keys that are not in the type might be present on the object at runtime!

```typescript
const o = { p: 33, k: "ok", r: false };
const x = objectKeys<{ p: number; k: string }>(o);
//x is of type ("p" | "k")[] but actually x === ["p", "k", "r"]
```

{% endhint %}


# exclude

Returns a function that you can use as the argument for Array.prototype.filter to exclude one or more primitive values from an array.

## Practical example

```typescript
import { exclude } from "tsafe/exclude";

type Circle = {
	type: "circle";
	radius: number;
};

type Square = {
	type: "square";
	sideLength: number;
};

type Shape = Circle | Square;

declare const shapes: Shape[];

//Assumes we want to do something for every Circle

shapes
	.map(shape => (shape.type === "circle" ? shape : null))
	.filter(exclude(null))
	.forEach(circle => {
		//Here circle is of type Circle
		//if we had used .filter(shape=> shape.type === "circle")
		//it would be functionally the same but circle would be of type
		//Shape
	});
```

## Basic examples

```typescript
import { exclude } from "tsafe/exclude";

const arr = ["a", "b", "c", "d"] as const;
const newArr = arr.filter(exclude("a"));

//type of newArr is ("b" | "c" | "d")[]
//value of newArr is ["b", "c", "d"]
```

You can also exclude more than on element:

```typescript
import { exclude } from "tsafe/exclude";

const arr = ["a", "b", "c", "d"] as const;
const newArr = arr.filter(exclude(["a", "b"]));

//type of newArr is ("c" | "d")[]
//value of newArr is ["c", "d"]
```


# isAmong

Let's say we have an union type like:  <br>

{% code title="Names.ts" %}

```typescript
export const names = ["foo", "bar", "baz"] as const;
export type Name = typeof names[number];
```

{% endcode %}

isAmong enables to test if a given values is one of the names

```typescript
import { isAmong } from "tsafe/isAmong";
import { names, type Names } from "./Names";

declare value: "foo" | "bar" | "something else";

if( isAmong(names, value) ){
  // Here value is of type "foo" | "bar"
  // (the intesection of the type of value before the test and Name)
}
```

If we just have the type and not the exhausive array:

```typescript
import { assert, type Equals } from "tsafe/assert";
import { isAmong } from "tsafe/isAmong";
import type { Names } from "./Names";

const names = ["foo", "bar", "baz"] as const;

assert<Equals<typeof names, Names>>;

declare value: string;

if( isAmong(names, value) ){
   // Here value is of type Names
}
```


# symToStr

Get the name of a symbol as typed string.

```typescript
import { symToStr } from "tsafe/symToStr";

declare const foo: any;

//str is of type "foo" and str === "foo"
const str = symToStr({ foo });
```

#### Without `symToStr`

```typescript
export const myFunctionX = () => {};

export const name = "myFunctionX";
```

If you happen to rename \`myFunctionX\` into something else it is easy to forget to rename the exported name as well.

#### With `symToStr`

```typescript
import { symToStr } from "tsafe/symToStr";

export const myFunctionX = () => {};

export const name = symToStr({ myFunctionX });
//           ^name is of type "myFunctionX"
```


# ReturnType

Like the builtin helper but more convenient to use.

There is two major pain point with [the default ReturnType](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype):

### Used with async function

If you have a function like:

```typescript
type Shape = {};
async function getShape(): Promise<Shape> {
	return {};
}
```

And you are trying to extract `Shape`, when you use the default return type:

```typescript
type shape = ReturnType<typeof getShape>;
//    ^ shape is Promise<Shape> 😤
```

With `tsafe`'s ReturnType

```typescript
import type { ReturnType } from "tsafe";

type shape = ReturnType<typeof getShape>;
//    ^ shape is Shape 😊
```

### Used with function that can be `undefined`

Let's say we have an interface defined as such:

```typescript
export type Api = {
	getShape?: () => Shape;
};
```

And we want to extract the type `Shape`, using the default `ReturnType` we have to do:

```typescript
type shape = ReturnType<NonNullable<Api["getShape"]>>;
```

With the ReturnType of `tsafe` you don't need `NonNullable`

```typescript
import type { ReturnType } from "tsafe";

type shape = ReturnType<Api["getShape"]>;
```


# Parameters

Same as [the builtin-type](https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype) but works also with nullable function type. Analogous to [`ReturnType`](/returntype#used-with-function-that-can-be-undefined).

```typescript
import type { Parameters } from "tsafe/Parameters";

declare const myFunction: (a: string) => void | null;

type args = Parameters<typeof myFunction>;
// ^ args is [a: string]
```


# Param0

Get a function's first parameter

Parameter of a function are often passed wrapped into an object, React props is a notable example:

```typescript
function MyComponent(props: Props) {
	return <>...</>;
}
```

To extract `Props` you can use:

```typescript
import type { Param0 } from "tsafe";

type props = Param0<typeof MyComponent>;
```

It's kind of the same of doing:

```typescript
type props = Parameters<typeof MyComponent>[0];
```

but

```typescript
declare function fun(): number;

type FunParams = Param0<typeof fun>;
//   ^void (instead of never)
```

and

```typescript
declare function fun(params?: { foo: string }): void;

type FunParams = Param0<typeof fun>;
//   ^ { foo: string; } ( instead of { foo: string; } | undefined )
```


# typeGuard

Aims at making the most of the [`value is T`](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) statement.

Implementation:

```typescript
export function typeGuard<T>(value: any, isMatched: boolean): value is T {
	return isMatched;
}
```

## Use case 1: Tell the compiler what assertion can be made on a given variable if a given test returns true.

```typescript
import { typeGuard } from "tsafe/typeGuard";

type Circle = { type: "CIRCLE"; radius: number };
type Square = { type: "SQUARE"; sideLength: number };
type Shape = Circle | Square;

declare const shape: Shape;

if (typeGuard<Circle>(shape, shape.type.startsWith("C"))) {
	//The developer knows the shape is is a CIRCLE,
	//TypeScript can't tell but trusts the developer.
	shape.radius;
} else {
	shape.sideLength;
}
```

Usage in conjonction with assert:

```typescript
import * as fs from "fs";
import { assert, type Equals } from "tsafe/assert";
import { typeGuard } from "tsafe/typeGuard";
import { z } from "zod";

type Person = {
    name: string;
    age: number;
};

const zPerson = z.object({
    name: z.string(),
    age: z.number()
});

assert<Equals<z.infer<typeof zPerson>, Person>>;

export function getAge(filePath: string): number {
    const person = JSON.parse(fs.readFileSync(filePath).toString("utf8")) as unknown;

    // After this statement typescripts knows that `person` is of type `Person`
    assert(typeGuard<Person>(person, zPerson.safeParse(person).success));

    return person.age;
}
```

## Use case 2: Helper for safely build other type guards

```typescript
import { typeGuard } from "tsafe";
type SetLike<T> = { values: () => {} };

export function matchSetLike<T>(set: any): set is SetLike<T> {
	return (
		set instanceof Object &&
		typeGuard<SetLike<T>>(set, true) &&
		typeof set.values === "function" &&
		/Set/.test(Object.getPrototypeOf(set).constructor.name)
	);
}
```


# capitalize/uncapitalize

Runtime implementation of the Capitalize helper type.

### `capitalize()`

```typescript
import { assert, type Equals } from "tsafe/assert";
import { capitalize } from "tsafe/capitalize";

const str = "foo";

const capitalizedStr = capitalize(str);

assert<Equals<typeof capitalizedStr, "Foo">>();
assert(capitalizedStr === "Foo");

//NOTE: There is a 'Capitalize' builtin type in TypeScript such that:
assert<Equals<Capitalize<"foo">, "Foo">>;
```

### `uncapitalize()`

```typescript
import { assert, type Equals } from "tsafe/assert";
import { uncapitalize } from "tsafe/uncapitalize";

const capitalizedStr = "Foo";

const str = uncapitalize(capitalizedStr);

assert<Equals<typeof str, "foo">>();
assert(str === "foo");

//NOTE: There is a 'Uncapitalize' builtin type in TypeScript such that:
assert<Equals<Uncapitalize<"Foo">, "foo">>;
```


# MethodNames

This utility type takes an Api interface as type argument and returns a union type of all the property names whose values are functions.

## Example:

```typescript
import type { MethodNames } from "tsafe";

type T = {
	x: number;
	y: number;
	method1(): void;
	method2(): void;
};

type TMethodNames = MethodNames<T>;

//resulting type is: "method1" | "method2"
```

The result will be the same if one or more of the methods are optional.

```typescript
import type { MethodNames } from "tsafe";

type T = {
	x: number;
	y: number;
	method1(): void;
	method2?(): void;
};

type TMethodNames = MethodNames<T>;

//resulting type is: "method1" | "method2"
```


# isPromiseLike

With this function we can check if its argument is like a `Promise`. In other words, if its argument has a method that is named `then`.

## Quick example

```typescript
import { isPromiseLike } from "tsafe/isPromiseLike";

const simulateNetworkDelay = new Promise<void>(resolve =>
	setTimeout(resolve, 1000)
);

const result = isPromiseLike(simulateNetworkDelay);

//result === true;
```

## Complementary example

If we have an object that has a method named `then`:

```typescript
import { isPromiseLike } from "tsafe/isPromiseLike";

const objPromiseLike = {
	then: () => null,
	x: 3,
	y: 4,
};

const result = isPromiseLike(objPromiseLike);

//result === true;
```


# flip

Flip the value of a boolean without having to reference it twice.

## Quick Example:

```typescript
import { flip } from "tsafe/flip";

const obj = {
	is_: false,
};

flip(obj, "is_");

//obj.is_ is now set to true
```

## In more detail:

When you have an object that contains another object that contains a boolean, and you wish to flip the value of that boolean for example, you would usually do as follows.

```typescript
const obj = {
	innerObj: {
		is_: false,
		x: 44,
		y: 33,
	},
};

obj.innerObj.is_ = !obj.innerObj.is_;
```

With the `flip` function, the task will be a bit less tedious.

```typescript
flip(obj.innerObj, "is_");
```

The first argument is the object that contains the boolean value, and the second, is the key of the boolean property. Typescript will infer the key(s) of type boolean as illustrated below.

![](/files/93ieQk3nVOTdjPX5Rp5m)


# objectEntries

Like Object.entries() but with a better return type.

Functionally equal to `Object.entries` but features a return type more precise than just `[string, T][].`

```typescript
import { assert, type Equals, objectEntries } from "tsafe";

//    v entries is of type ["a", string], ["b", number], ["c", boolean]
const entries = objectEntries({
	a: "foo",
	b: 33,
	c: true,
});

assert<
	Equals<typeof entries, (["a", string] | ["b", number] | ["c", boolean])[]>
>();
```

{% hint style="warning" %}
WARNING: [See `objectKeys()`'s warning](/objectkeys).
{% endhint %}


# objectFromEntries

Like Object.fromEntries() but with a better return type

Functionally identical to `Object.fromEntries()` but instead of returning but its return type more precise than just `{ [k: sting]: any; }`.

```typescript
import { assert, type Equals, objectFromEntries } from "tsafe";

const entries = [
	["a", "foo"],
	["b", 33],
	["c", true as boolean],
] as const;

const obj = objectFromEntries(entries);
//    ^ obj is of type { a: "foo"; b: 33; c: boolean; }

assert<
	Equals<
		typeof obj,
		{
			a: "foo";
			b: 33;
			c: boolean;
		}
	>
>;
```


# UnionToIntersection

```typescript

type A = { foo: string; };
type B = { bar: number; };

type Got = UnionToIntersection<A | B>;
type Expected = A & B;

assert<Equals<Got,Expected>>();
```

Example:

```typescript
import type { UnionToIntersection } from "tsafe";

const o1= {
  "p1": { "a": "foo" },
  "p2": { "b": "foo", "c": "foo" }
};

const o2: UnionToIntersection<(typeof o1)[keyof typeof o1]> = {} as any;

objectKeys(o1).forEach(key=> Object.assign(o2, o1[key]));

//o2 is of type { a: string; b: string; c: string; }
```

*Credit goes to* [*jcalz*](https://stackoverflow.com/users/2887218/jcalz) *for this type,* [*see SO answer*](https://stackoverflow.com/a/50375286/3731798)*.*


# withDefaults

Like Function.prototype.bind() but for a function that  receives their parameters wrapped in an object.

## Quick example

```typescript
import { withDefaults } from "tsafe/lab/withDefaults";

function sum(params: { x: number; y: number; z: number }): number {
	const { x, y, z } = params;
	return x + y + z;
}

// sumWd is of type: (params: { y: number; z: number; })=> number
const sumWd = withDefaults(sum, { x: 10 });

console.log(sumWd({ y: 1, z: 2 })); // Prints "13" ( 10 + 1 + 2 )

console.log(sumWd({ y: 3, z: 4 })); // Prints "17" ( 10 + 3 + 4 )

console.log(
	sumWd({
		y: 3,
		z: 4,
		defaultsOverwrite: {
			x: [20],
		},
	})
); // Prints "27" ( 20 + 3 + 4 )
```

## In greater detail

If you have a function with a set of parameters wrapped in an object, and you wish to call this function multiple times with the same value for one or more of the parameters, `withDefaults` enables you to instantly generate a new function with these parameters already set so that you do not have to fill them in at every call.

Consider a function that takes two numbers as parameters and returns the sum of them.

```typescript
function sum(params: { x: number; y: number }) {
	const { x, y } = params;
	return x + y;
}
```

Suppose we want to set the value of `x` for example.

```typescript
const sumWd = withDefaults(sum, { x: 33 });
```

`sumWd` is a proxy to our original function with `x` set to `33`. `withDefaults` first argument is the original function, and the second is an object with the parameters of the original function as properties. Naturally, the properties are inferred by typescript as shown below.

![](/files/aqJOS4QFR7RR8LMxNLMy)

Now we can call `sumWd` as many times as we want without having to set `x`. Its value will always be `33`.

```typescript
const result = sumWd({ y: 10 }); //43
```

The value of `result` will be `43`. Typescript infers the remaining value to be set:

![](/files/pzBBNSfhtkRM19khtlrE)

### Overwriting the injected value:

```typescript
const result = sumWd({
	y: 10,
	defaultsOverwrite: { x: [23] },
}); // 33
```

The type of `x` in `defaultsOverwrite` is `[number] | undefined` so that `undefined` cannot be assigned to `x` if that is not its type.


# UnpackPromise

Deprecated. Extract the packed type of a Promise

{% hint style="danger" %}
In TypeScript 4.5 have been introduced the [`Awaited`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#the-awaited-type-and-promise-improvements) type that does just what UnpackPromise does.
{% endhint %}

```typescript
declare const prStr: Promise<string>;

//str is of type string
declare const str: UnpackPromise<typeof pr>;
```


