3.8.86 • Published 1 year ago

@taktikorg/quia-exercitationem v3.8.86

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

@taktikorg/quia-exercitationem

Type-safe implementation of invariant with positionals.

Motivation

Type-safely

This implementation asserts the given predicate expression so it's treated as non-nullable after the invariant call:

// Regular invariant:
invariant(user, 'Failed to fetch')
user?.firstName // "user" is possibly undefined

// Outvariant:
invariant(user, 'Failed to fetch')
user.firstName // OK, "invariant" ensured the "user" exists

Positionals support

This implementation uses rest parameters to support dynamic number of positionals:

invariant(predicate, 'Expected %s but got %s', 'one', false)

What is this for?

Invariant is a shorthand function that asserts a given predicate and throws an error if that predicate is false.

Compare these two pieces of code identical in behavior:

if (!token) {
  throw new Error(`Expected a token to be set but got ${typeof token}`)
}
import { invariant } from '@taktikorg/quia-exercitationem'

invariant(token, 'Expected a token to be set but got %s', typeof token)

Using invariant reduces the visual nesting of the code and leads to cleaner error messages thanks to formatted positionals (i.e. the %s (string) positional above).

Usage

Install

npm install @taktikorg/quia-exercitationem
# or
yarn add @taktikorg/quia-exercitationem

You may want to install this library as a dev dependency (-D) based on your usage.

Write an assertion

import { invariant } from '@taktikorg/quia-exercitationem'

invariant(user, 'Failed to load: expected user, but got %o', user)

Positionals

The following positional tokens are supported:

TokenExpected value type
%sString
%d/%iNumber
%jJSON (non-stringified)
%oArbitrary object or object-like (i.e. a class instance)

Whenever present in the error message, a positional token will look up the value to insert in its place from the arguments given to invariant.

invariant(
  false,
  'Expected the "%s" property but got %j',
  // Note that positionals are sensitive to order:
  // - "firstName" replaces "%s" because it's first.
  // - {"id":1} replaces "%j" because it's second.
  'firstName',
  {
    id: 1,
  }
)

Polymorphic errors

It is possible to throw a custom Error instance using invariant.as:

import { invariant } from '@taktikorg/quia-exercitationem'

class NetworkError extends Error {
  constructor(message) {
    super(message)
  }
}

invariant.as(NetworkError, res.fulfilled, 'Failed to handle response')

Note that providing a custom error constructor as the argument to invariant.as requires the custom constructor's signature to be compatible with the Error class constructor.

If your error constructor has a different signature, you can pass a function as the first argument to invariant.as that creates a new custom error instance.

import { invariant } from '@taktikorg/quia-exercitationem'

class NetworkError extends Error {
  constructor(statusCode, message) {
    super(message)
    this.statusCode = statusCode
  }
}

invariant.as(
  (message) => new NetworkError(500, message),
  res.fulfilled,
  'Failed to handle response'
)

Abstract the error into helper functions for flexibility:

function toNetworkError(statusCode) {
  return (message) => new NetworkError(statusCode, message)
}

invariant.as(toNetworkError(404), res?.user?.id, 'User Not Found')
invariant.as(toNetworkError(500), res.fulfilled, 'Internal Server Error')

Contributing

Please open an issue or submit a pull request if you wish to contribute. Thank you.

3.8.86

1 year ago

3.8.85

1 year ago

3.8.84

1 year ago

3.7.84

1 year ago

3.7.83

1 year ago

3.7.82

1 year ago

3.7.81

1 year ago

3.7.80

1 year ago

3.7.79

1 year ago

3.6.79

1 year ago

3.6.78

1 year ago

3.6.77

1 year ago

3.6.76

1 year ago

3.6.75

1 year ago

3.6.74

1 year ago

3.6.73

1 year ago

3.6.72

1 year ago

3.6.71

1 year ago

3.5.71

1 year ago

3.5.70

1 year ago

3.5.69

1 year ago

3.5.68

1 year ago

3.5.67

1 year ago

3.5.66

1 year ago

3.5.65

1 year ago

3.4.65

1 year ago

3.4.64

1 year ago

3.4.63

1 year ago

3.4.62

1 year ago

3.4.61

1 year ago

3.4.60

1 year ago

3.4.59

1 year ago

3.4.58

1 year ago

3.4.57

1 year ago

3.4.56

1 year ago

3.4.55

1 year ago

3.4.54

1 year ago

3.3.54

1 year ago

3.3.53

1 year ago

3.3.52

1 year ago

3.3.51

1 year ago

3.3.50

1 year ago

3.3.49

1 year ago

3.3.48

1 year ago

3.3.47

1 year ago

3.3.46

1 year ago

3.3.45

1 year ago

3.3.44

1 year ago

3.3.43

1 year ago

3.3.42

1 year ago

3.3.41

1 year ago

3.3.40

1 year ago

3.3.39

1 year ago

3.3.38

1 year ago

3.3.37

1 year ago

3.3.36

1 year ago

3.3.35

1 year ago

3.3.34

1 year ago

3.3.33

1 year ago

2.3.33

1 year ago

2.3.32

1 year ago

2.2.32

1 year ago

2.2.31

1 year ago

2.2.30

1 year ago

2.2.29

1 year ago

2.2.28

1 year ago

2.2.27

1 year ago

2.2.26

1 year ago

2.2.25

1 year ago

2.1.25

1 year ago

2.1.24

1 year ago

2.1.23

1 year ago

2.1.22

1 year ago

2.1.21

1 year ago

2.1.20

1 year ago

2.1.19

1 year ago

1.1.19

1 year ago

1.1.18

1 year ago

1.0.18

1 year ago

1.0.17

1 year ago

1.0.16

1 year ago

1.0.15

1 year ago

1.0.14

1 year ago

1.0.13

1 year ago

1.0.12

1 year ago

1.0.11

1 year ago

1.0.10

1 year ago

1.0.9

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago