Add assertion type guards

Uses the typescript v3.7 feature `asserts value is T` to create `assert` variants of the `is` type guards. The assertions are used to narrow types at compile time, and to throw `TypeError` at runtime for values which are not of the correct type.

```typescript
import {assert} from '@sindresorhus/is';

assert.string(foo);
```

- Each method in `is` is wrapped and mirrored in `assert`.
- Tests for `is` are duplicated for `assert`.

Notes

- The explicit typing in `interface Assert` is required for typescript to acknowledge the assertions.
- Due to the assertions requiring explicit typing, using ` property for is.assert.string()` (and so on) would require using `namespace is`, which was removed in #78. This also means that `assert` needs to be exported separately.
- Custom descriptions are used to enhance some assertion error messages. The value is not included in the error message.
- Could perhaps use Node.js' fitting `AssertionError` on the server-side, but it would require an `import`.

Fixes #91.

See

- https://github.com/sindresorhus/is/issues/91
- https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions
- https://github.com/microsoft/TypeScript/pull/32695
This commit is contained in:
Joel Purra 2019-11-08 15:44:55 +01:00
parent c842cc260f
commit 1e89fb4d9c
3 changed files with 593 additions and 25 deletions

View file

@ -11,6 +11,7 @@ For example, `is.string('🦄') //=> true`
- Written in TypeScript
- [Extensive use of type guards](#type-guards)
- [Supports type assertions](#type-assertions)
- Actively maintained
- 2 million weekly downloads
@ -37,6 +38,15 @@ is.number(6);
//=> true
```
Assertions perform the same type checks, but throw errors if the type does not match.
```js
const {assert} = require('@sindresorhus/is');
assert.string(foo);
//=> foo is known to be a string
```
## API
@ -425,6 +435,30 @@ padLeft('🦄', '🌈');
//=> '🌈🦄'
```
## Type assertions
The type guards are also available as [typescript assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions), which throw an error for unexpected types. It is a convenient one-line version of the often repetitive "if-not-expected-type-throw" pattern.
```ts
import {assert} from '@sindresorhus/is';
const handleMovieRatingApiResponse = (response: unknown) => {
assert.plainObject(response);
// `response` is typed as a plain `object` with `unknown` properties
assert.number(response.rating);
// `response.rating` is typed as a `number`
assert.string(response.title);
// `response.title` is typed as a `string`
return `${response.title} (${response.rating * 10})`;
};
handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'});
//=> 'The Matrix (8.7)'
handleMovieRatingApiResponse({status: 'system maintenance'});
//=> throws error
```
## FAQ