Merge branch 'master' of https://github.com/sindresorhus/is.git into async-generator

This commit is contained in:
forresst 2020-01-28 08:15:21 +01:00
commit 1264ed0c87
5 changed files with 856 additions and 39 deletions

View file

@ -4,6 +4,7 @@
"description": "Type check values",
"license": "MIT",
"repository": "sindresorhus/is",
"funding": "https://github.com/sindresorhus/is?sponsor=1",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
@ -46,20 +47,20 @@
"types"
],
"devDependencies": {
"@sindresorhus/tsconfig": "^0.6.0",
"@sindresorhus/tsconfig": "^0.7.0",
"@types/jsdom": "^12.2.4",
"@types/node": "^12.12.6",
"@types/zen-observable": "^0.8.0",
"@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.11.0",
"@typescript-eslint/eslint-plugin": "^2.17.0",
"@typescript-eslint/parser": "^2.17.0",
"ava": "^2.1.0",
"del-cli": "^2.0.0",
"eslint-config-xo-typescript": "^0.15.0",
"eslint-config-xo-typescript": "^0.24.1",
"jsdom": "^15.0.0",
"rxjs": "^6.4.0",
"tempy": "^0.3.0",
"ts-node": "^8.3.0",
"typescript": "^3.7.2",
"typescript": "^3.7.5",
"xo": "^0.25.3",
"zen-observable": "^0.8.8"
},
@ -80,6 +81,9 @@
"extensions": [
"ts"
],
"parserOptions": {
"project": "./tsconfig.xo.json"
},
"globals": [
"BigInt",
"BigInt64Array",

View file

@ -6,22 +6,20 @@ For example, `is.string('🦄') //=> true`
<img src="header.gif" width="182" align="right">
## Highlights
- Written in TypeScript
- [Extensive use of type guards](#type-guards)
- [Supports type assertions](#type-assertions)
- Actively maintained
- 2 million weekly downloads
## Install
```
$ npm install @sindresorhus/is
```
## Usage
```js
@ -37,6 +35,23 @@ is.number(6);
//=> true
```
[Assertions](#type-assertions) perform the same type checks, but throw an error if the type does not match.
```js
const {assert} = require('@sindresorhus/is');
assert.string(2);
//=> Error: Expected value which is `string`, received value of type `number`.
```
And with TypeScript:
```ts
import {assert} from '@sindresorhus/is';
assert.string(foo);
// `foo` is now typed as a `string`.
```
## API
@ -428,7 +443,6 @@ is.all(is.string, '🦄', [], 'unicorns');
//=> false
```
## Type guards
When using `is` together with TypeScript, [type guards](http://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types) are being used extensively to infer the correct type inside if-else statements.
@ -457,6 +471,32 @@ padLeft('🦄', '🌈');
//=> '🌈🦄'
```
## Type assertions
The type guards are also available as [type 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 now typed as a plain `object` with `unknown` properties.
assert.number(response.rating);
// `response.rating` is now typed as a `number`.
assert.string(response.title);
// `response.title` is now typed as a `string`.
return `${response.title} (${response.rating * 10})`;
};
handleMovieRatingApiResponse({rating: 0.87, title: 'The Matrix'});
//=> 'The Matrix (8.7)'
// This throws an error.
handleMovieRatingApiResponse({rating: '🦄'});
```
## FAQ
@ -475,14 +515,12 @@ For the ones I found, pick 3 of these.
The most common mistakes I noticed in these modules was using `instanceof` for type checking, forgetting that functions are objects, and omitting `symbol` as a primitive.
## For enterprise
Available as part of the Tidelift Subscription.
The maintainers of @sindresorhus/is and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-sindresorhus-is?utm_source=npm-sindresorhus-is&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Related
- [ow](https://github.com/sindresorhus/ow) - Function argument validation for humans
@ -496,7 +534,6 @@ The maintainers of @sindresorhus/is and thousands of other packages are working
- [is-blob](https://github.com/sindresorhus/is-blob) - Check if a value is a Blob - File-like object of immutable, raw data
- [has-emoji](https://github.com/sindresorhus/has-emoji) - Check whether a string has any emoji
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)

View file

@ -284,8 +284,8 @@ is.typedArray = (value: unknown): value is TypedArray => {
};
export interface ArrayLike<T> {
readonly length: number;
readonly [index: number]: T;
readonly length: number;
}
const isValidLength = (value: unknown): value is number => is.safeInteger(value) && value >= 0;
@ -391,6 +391,231 @@ const predicateOnArray = (method: ArrayMethod, predicate: Predicate, values: unk
is.any = (predicate: Predicate, ...values: unknown[]): boolean => predicateOnArray(Array.prototype.some, predicate, values);
is.all = (predicate: Predicate, ...values: unknown[]): boolean => predicateOnArray(Array.prototype.every, predicate, values);
const assertType = (condition: boolean, description: string, value: unknown): asserts condition => {
if (!condition) {
throw new TypeError(`Expected value which is \`${description}\`, received value of type \`${is(value)}\`.`);
}
};
export const enum AssertionTypeDescription {
class_ = 'Class',
numericString = 'string with a number',
nullOrUndefined = 'null or undefined',
iterable = 'Iterable',
asyncIterable = 'AsyncIterable',
nativePromise = 'native Promise',
urlString = 'string with a URL',
truthy = 'truthy',
falsy = 'falsy',
nan = 'NaN',
primitive = 'primitive',
integer = 'integer',
safeInteger = 'integer',
plainObject = 'plain object',
arrayLike = 'array-like',
typedArray = 'TypedArray',
domElement = 'Element',
nodeStream = 'Node.js Stream',
infinite = 'infinite number',
emptyArray = 'empty array',
nonEmptyArray = 'non-empty array',
emptyString = 'empty string',
nonEmptyString = 'non-empty string',
emptyStringOrWhitespace = 'empty string or whitespace',
emptyObject = 'empty object',
nonEmptyObject = 'non-empty object',
emptySet = 'empty set',
nonEmptySet = 'non-empty set',
emptyMap = 'empty map',
nonEmptyMap = 'non-empty map',
evenInteger = 'even integer',
oddInteger = 'odd integer',
directInstanceOf = 'T',
inRange = 'in range',
any = 'predicate returns truthy for any value',
all = 'predicate returns truthy for all values',
}
// Type assertions have to be declared with an explicit type.
interface Assert {
// Unknowns.
undefined: (value: unknown) => asserts value is undefined;
string: (value: unknown) => asserts value is string;
number: (value: unknown) => asserts value is number;
bigint: (value: unknown) => asserts value is bigint;
// eslint-disable-next-line @typescript-eslint/ban-types
function_: (value: unknown) => asserts value is Function;
null_: (value: unknown) => asserts value is null;
class_: (value: unknown) => asserts value is Class;
boolean: (value: unknown) => asserts value is boolean;
symbol: (value: unknown) => asserts value is symbol;
numericString: (value: unknown) => asserts value is string;
array: <T = unknown>(value: unknown) => asserts value is T[];
buffer: (value: unknown) => asserts value is Buffer;
nullOrUndefined: (value: unknown) => asserts value is null | undefined;
object: (value: unknown) => asserts value is Record<string, unknown>;
iterable: <T = unknown>(value: unknown) => asserts value is Iterable<T>;
asyncIterable: <T = unknown>(value: unknown) => asserts value is AsyncIterable<T>;
generator: (value: unknown) => asserts value is Generator;
nativePromise: <T = unknown>(value: unknown) => asserts value is Promise<T>;
promise: <T = unknown>(value: unknown) => asserts value is Promise<T>;
generatorFunction: (value: unknown) => asserts value is GeneratorFunction;
// eslint-disable-next-line @typescript-eslint/ban-types
asyncFunction: (value: unknown) => asserts value is Function;
// eslint-disable-next-line @typescript-eslint/ban-types
boundFunction: (value: unknown) => asserts value is Function;
regExp: (value: unknown) => asserts value is RegExp;
date: (value: unknown) => asserts value is Date;
error: (value: unknown) => asserts value is Error;
map: <TKey = unknown, TValue = unknown>(value: unknown) => asserts value is Map<TKey, TValue>;
set: <T = unknown>(value: unknown) => asserts value is Set<T>;
weakMap: <TKey extends object = object, TValue = unknown>(value: unknown) => asserts value is WeakMap<TKey, TValue>;
weakSet: <T extends object = object>(value: unknown) => asserts value is WeakSet<T>;
int8Array: (value: unknown) => asserts value is Int8Array;
uint8Array: (value: unknown) => asserts value is Uint8Array;
uint8ClampedArray: (value: unknown) => asserts value is Uint8ClampedArray;
int16Array: (value: unknown) => asserts value is Int16Array;
uint16Array: (value: unknown) => asserts value is Uint16Array;
int32Array: (value: unknown) => asserts value is Int32Array;
uint32Array: (value: unknown) => asserts value is Uint32Array;
float32Array: (value: unknown) => asserts value is Float32Array;
float64Array: (value: unknown) => asserts value is Float64Array;
bigInt64Array: (value: unknown) => asserts value is BigInt64Array;
bigUint64Array: (value: unknown) => asserts value is BigUint64Array;
arrayBuffer: (value: unknown) => asserts value is ArrayBuffer;
sharedArrayBuffer: (value: unknown) => asserts value is SharedArrayBuffer;
dataView: (value: unknown) => asserts value is DataView;
urlInstance: (value: unknown) => asserts value is URL;
urlString: (value: unknown) => asserts value is string;
truthy: (value: unknown) => asserts value is unknown;
falsy: (value: unknown) => asserts value is unknown;
nan: (value: unknown) => asserts value is unknown;
primitive: (value: unknown) => asserts value is Primitive;
integer: (value: unknown) => asserts value is number;
safeInteger: (value: unknown) => asserts value is number;
plainObject: (value: unknown) => asserts value is {[key: string]: unknown};
typedArray: (value: unknown) => asserts value is TypedArray;
arrayLike: <T = unknown>(value: unknown) => asserts value is ArrayLike<T>;
domElement: (value: unknown) => asserts value is Element;
observable: (value: unknown) => asserts value is ObservableLike;
nodeStream: (value: unknown) => asserts value is NodeStream;
infinite: (value: unknown) => asserts value is number;
emptyArray: (value: unknown) => asserts value is never[];
nonEmptyArray: (value: unknown) => asserts value is unknown[];
emptyString: (value: unknown) => asserts value is '';
nonEmptyString: (value: unknown) => asserts value is string;
emptyStringOrWhitespace: (value: unknown) => asserts value is string;
emptyObject: (value: unknown) => asserts value is {[key: string]: never};
nonEmptyObject: (value: unknown) => asserts value is {[key: string]: unknown};
emptySet: (value: unknown) => asserts value is Set<never>;
nonEmptySet: (value: unknown) => asserts value is Set<unknown>;
emptyMap: (value: unknown) => asserts value is Map<never, never>;
nonEmptyMap: (value: unknown) => asserts value is Map<unknown, unknown>;
// Numbers.
evenInteger: (value: number) => asserts value is number;
oddInteger: (value: number) => asserts value is number;
// Two arguments.
directInstanceOf: <T>(instance: unknown, class_: Class<T>) => asserts instance is T;
inRange: (value: number, range: number | number[]) => asserts value is number;
// Variadic functions.
any: (predicate: Predicate, ...values: unknown[]) => void | never;
all: (predicate: Predicate, ...values: unknown[]) => void | never;
}
export const assert: Assert = {
// Unknowns.
undefined: (value: unknown): asserts value is undefined => assertType(is.undefined(value), TypeName.undefined, value),
string: (value: unknown): asserts value is string => assertType(is.string(value), TypeName.string, value),
number: (value: unknown): asserts value is number => assertType(is.number(value), TypeName.number, value),
bigint: (value: unknown): asserts value is bigint => assertType(is.bigint(value), TypeName.bigint, value),
// eslint-disable-next-line @typescript-eslint/ban-types
function_: (value: unknown): asserts value is Function => assertType(is.function_(value), TypeName.Function, value),
null_: (value: unknown): asserts value is null => assertType(is.null_(value), TypeName.null, value),
class_: (value: unknown): asserts value is Class => assertType(is.class_(value), AssertionTypeDescription.class_, value),
boolean: (value: unknown): asserts value is boolean => assertType(is.boolean(value), TypeName.boolean, value),
symbol: (value: unknown): asserts value is symbol => assertType(is.symbol(value), TypeName.symbol, value),
numericString: (value: unknown): asserts value is string => assertType(is.numericString(value), AssertionTypeDescription.numericString, value),
array: <T = unknown>(value: unknown): asserts value is T[] => assertType(is.array(value), TypeName.Array, value),
buffer: (value: unknown): asserts value is Buffer => assertType(is.buffer(value), TypeName.Buffer, value),
nullOrUndefined: (value: unknown): asserts value is null | undefined => assertType(is.nullOrUndefined(value), AssertionTypeDescription.nullOrUndefined, value),
object: (value: unknown): asserts value is Record<string, unknown> => assertType(is.object(value), TypeName.Object, value),
iterable: <T = unknown>(value: unknown): asserts value is Iterable<T> => assertType(is.iterable(value), AssertionTypeDescription.iterable, value),
asyncIterable: <T = unknown>(value: unknown): asserts value is AsyncIterable<T> => assertType(is.asyncIterable(value), AssertionTypeDescription.asyncIterable, value),
generator: (value: unknown): asserts value is Generator => assertType(is.generator(value), TypeName.Generator, value),
nativePromise: <T = unknown>(value: unknown): asserts value is Promise<T> => assertType(is.nativePromise(value), AssertionTypeDescription.nativePromise, value),
promise: <T = unknown>(value: unknown): asserts value is Promise<T> => assertType(is.promise(value), TypeName.Promise, value),
generatorFunction: (value: unknown): asserts value is GeneratorFunction => assertType(is.generatorFunction(value), TypeName.GeneratorFunction, value),
// eslint-disable-next-line @typescript-eslint/ban-types
asyncFunction: (value: unknown): asserts value is Function => assertType(is.asyncFunction(value), TypeName.AsyncFunction, value),
// eslint-disable-next-line @typescript-eslint/ban-types
boundFunction: (value: unknown): asserts value is Function => assertType(is.boundFunction(value), TypeName.Function, value),
regExp: (value: unknown): asserts value is RegExp => assertType(is.regExp(value), TypeName.RegExp, value),
date: (value: unknown): asserts value is Date => assertType(is.date(value), TypeName.Date, value),
error: (value: unknown): asserts value is Error => assertType(is.error(value), TypeName.Error, value),
map: <TKey = unknown, TValue = unknown>(value: unknown): asserts value is Map<TKey, TValue> => assertType(is.map(value), TypeName.Map, value),
set: <T = unknown>(value: unknown): asserts value is Set<T> => assertType(is.set(value), TypeName.Set, value),
weakMap: <TKey extends object = object, TValue = unknown>(value: unknown): asserts value is WeakMap<TKey, TValue> => assertType(is.weakMap(value), TypeName.WeakMap, value),
weakSet: <T extends object = object>(value: unknown): asserts value is WeakSet<T> => assertType(is.weakSet(value), TypeName.WeakSet, value),
int8Array: (value: unknown): asserts value is Int8Array => assertType(is.int8Array(value), TypeName.Int8Array, value),
uint8Array: (value: unknown): asserts value is Uint8Array => assertType(is.uint8Array(value), TypeName.Uint8Array, value),
uint8ClampedArray: (value: unknown): asserts value is Uint8ClampedArray => assertType(is.uint8ClampedArray(value), TypeName.Uint8ClampedArray, value),
int16Array: (value: unknown): asserts value is Int16Array => assertType(is.int16Array(value), TypeName.Int16Array, value),
uint16Array: (value: unknown): asserts value is Uint16Array => assertType(is.uint16Array(value), TypeName.Uint16Array, value),
int32Array: (value: unknown): asserts value is Int32Array => assertType(is.int32Array(value), TypeName.Int32Array, value),
uint32Array: (value: unknown): asserts value is Uint32Array => assertType(is.uint32Array(value), TypeName.Uint32Array, value),
float32Array: (value: unknown): asserts value is Float32Array => assertType(is.float32Array(value), TypeName.Float32Array, value),
float64Array: (value: unknown): asserts value is Float64Array => assertType(is.float64Array(value), TypeName.Float64Array, value),
bigInt64Array: (value: unknown): asserts value is BigInt64Array => assertType(is.bigInt64Array(value), TypeName.BigInt64Array, value),
bigUint64Array: (value: unknown): asserts value is BigUint64Array => assertType(is.bigUint64Array(value), TypeName.BigUint64Array, value),
arrayBuffer: (value: unknown): asserts value is ArrayBuffer => assertType(is.arrayBuffer(value), TypeName.ArrayBuffer, value),
sharedArrayBuffer: (value: unknown): asserts value is SharedArrayBuffer => assertType(is.sharedArrayBuffer(value), TypeName.SharedArrayBuffer, value),
dataView: (value: unknown): asserts value is DataView => assertType(is.dataView(value), TypeName.DataView, value),
urlInstance: (value: unknown): asserts value is URL => assertType(is.urlInstance(value), TypeName.URL, value),
urlString: (value: unknown): asserts value is string => assertType(is.urlString(value), AssertionTypeDescription.urlString, value),
truthy: (value: unknown): asserts value is unknown => assertType(is.truthy(value), AssertionTypeDescription.truthy, value),
falsy: (value: unknown): asserts value is unknown => assertType(is.falsy(value), AssertionTypeDescription.falsy, value),
nan: (value: unknown): asserts value is unknown => assertType(is.nan(value), AssertionTypeDescription.nan, value),
primitive: (value: unknown): asserts value is Primitive => assertType(is.primitive(value), AssertionTypeDescription.primitive, value),
integer: (value: unknown): asserts value is number => assertType(is.integer(value), AssertionTypeDescription.integer, value),
safeInteger: (value: unknown): asserts value is number => assertType(is.safeInteger(value), AssertionTypeDescription.safeInteger, value),
plainObject: (value: unknown): asserts value is {[key: string]: unknown} => assertType(is.plainObject(value), AssertionTypeDescription.plainObject, value),
typedArray: (value: unknown): asserts value is TypedArray => assertType(is.typedArray(value), AssertionTypeDescription.typedArray, value),
arrayLike: <T = unknown>(value: unknown): asserts value is ArrayLike<T> => assertType(is.arrayLike(value), AssertionTypeDescription.arrayLike, value),
domElement: (value: unknown): asserts value is Element => assertType(is.domElement(value), AssertionTypeDescription.domElement, value),
observable: (value: unknown): asserts value is ObservableLike => assertType(is.observable(value), TypeName.Observable, value),
nodeStream: (value: unknown): asserts value is NodeStream => assertType(is.nodeStream(value), AssertionTypeDescription.nodeStream, value),
infinite: (value: unknown): asserts value is number => assertType(is.infinite(value), AssertionTypeDescription.infinite, value),
emptyArray: (value: unknown): asserts value is never[] => assertType(is.emptyArray(value), AssertionTypeDescription.emptyArray, value),
nonEmptyArray: (value: unknown): asserts value is unknown[] => assertType(is.nonEmptyArray(value), AssertionTypeDescription.nonEmptyArray, value),
emptyString: (value: unknown): asserts value is '' => assertType(is.emptyString(value), AssertionTypeDescription.emptyString, value),
nonEmptyString: (value: unknown): asserts value is string => assertType(is.nonEmptyString(value), AssertionTypeDescription.nonEmptyString, value),
emptyStringOrWhitespace: (value: unknown): asserts value is string => assertType(is.emptyStringOrWhitespace(value), AssertionTypeDescription.emptyStringOrWhitespace, value),
emptyObject: (value: unknown): asserts value is {[key: string]: never} => assertType(is.emptyObject(value), AssertionTypeDescription.emptyObject, value),
nonEmptyObject: (value: unknown): asserts value is {[key: string]: unknown} => assertType(is.nonEmptyObject(value), AssertionTypeDescription.nonEmptyObject, value),
emptySet: (value: unknown): asserts value is Set<never> => assertType(is.emptySet(value), AssertionTypeDescription.emptySet, value),
nonEmptySet: (value: unknown): asserts value is Set<unknown> => assertType(is.nonEmptySet(value), AssertionTypeDescription.nonEmptySet, value),
emptyMap: (value: unknown): asserts value is Map<never, never> => assertType(is.emptyMap(value), AssertionTypeDescription.emptyMap, value),
nonEmptyMap: (value: unknown): asserts value is Map<unknown, unknown> => assertType(is.nonEmptyMap(value), AssertionTypeDescription.nonEmptyMap, value),
// Numbers.
evenInteger: (value: number): asserts value is number => assertType(is.evenInteger(value), AssertionTypeDescription.evenInteger, value),
oddInteger: (value: number): asserts value is number => assertType(is.oddInteger(value), AssertionTypeDescription.oddInteger, value),
// Two arguments.
directInstanceOf: <T>(instance: unknown, class_: Class<T>): asserts instance is T => assertType(is.directInstanceOf(instance, class_), AssertionTypeDescription.directInstanceOf, instance),
inRange: (value: number, range: number | number[]): asserts value is number => assertType(is.inRange(value, range), AssertionTypeDescription.inRange, value),
// Variadic functions.
any: (predicate: Predicate, ...values: unknown[]): void | never => assertType(is.any(predicate, ...values), AssertionTypeDescription.any, values),
all: (predicate: Predicate, ...values: unknown[]): void | never => assertType(is.all(predicate, ...values), AssertionTypeDescription.all, values)
};
// Some few keywords are reserved, but we'll populate them for Node.js users
// See https://github.com/Microsoft/TypeScript/issues/2536
Object.defineProperties(is, {
@ -404,9 +629,21 @@ Object.defineProperties(is, {
value: is.null_
}
});
Object.defineProperties(assert, {
class: {
value: assert.class_
},
function: {
value: assert.function_
},
null: {
value: assert.null_
}
});
export default is;
// For CommonJS default export support
module.exports = is;
module.exports.default = is;
module.exports.assert = assert;

File diff suppressed because it is too large Load diff

6
tsconfig.xo.json Normal file
View file

@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"include": [
"test"
]
}