///
///
///
export type Class = new (...args: any[]) => T;
const objectTypeNames = [
'Function',
'Generator',
'AsyncGenerator',
'GeneratorFunction',
'AsyncGeneratorFunction',
'AsyncFunction',
'Observable',
'Array',
'Buffer',
'Object',
'RegExp',
'Date',
'Error',
'Map',
'Set',
'WeakMap',
'WeakSet',
'ArrayBuffer',
'SharedArrayBuffer',
'DataView',
'Promise',
'URL'
] as const;
type ObjectTypeName = typeof objectTypeNames[number];
const primitives = {
null: null,
undefined,
string: String(),
number: Number(),
bigint: BigInt(0),
boolean: Boolean(),
symbol: Symbol('')
} as const;
type PrimitiveTypeName = keyof typeof primitives;
export type Primitive = typeof primitives[PrimitiveTypeName];
function isPrimitiveTypeName(name: string): name is PrimitiveTypeName {
return Object.prototype.hasOwnProperty.call(primitives, name);
}
const typedArrays = {
Int8Array: new Int8Array(),
Uint8Array: new Uint8Array(),
Uint8ClampedArray: new Uint8ClampedArray(),
Int16Array: new Int16Array(),
Uint16Array: new Uint16Array(),
Int32Array: new Int32Array(),
Uint32Array: new Uint32Array(),
Float32Array: new Float32Array(),
Float64Array: new Float64Array(),
BigInt64Array: new BigInt64Array(),
BigUint64Array: new BigUint64Array()
} as const;
type TypedArrayTypeName = keyof typeof typedArrays;
export type TypedArray = typeof typedArrays[TypedArrayTypeName];
function isTypedArrayName(value: any): value is TypedArrayTypeName {
return Object.prototype.hasOwnProperty.call(typedArrays, value);
}
export type TypeName = ObjectTypeName | PrimitiveTypeName | TypedArrayTypeName;
const {toString} = Object.prototype;
const isOfType = (type: string) => (value: unknown): value is T => typeof value === type;
const getObjectType = (value: unknown): TypeName | undefined => {
const objectName = toString.call(value).slice(8, -1);
if (objectName) {
return objectName as TypeName;
}
return undefined;
};
const isObjectOfType = (type: TypeName) => (value: unknown): value is T => getObjectType(value) === type;
function is(value: unknown): TypeName {
switch (value) {
case null:
return 'null';
case true:
case false:
return 'boolean';
default:
}
switch (typeof value) {
case 'undefined':
return 'undefined';
case 'string':
return 'string';
case 'number':
return 'number';
case 'bigint':
return 'bigint';
case 'symbol':
return 'symbol';
default:
}
if (is.function_(value)) {
return 'Function';
}
if (is.observable(value)) {
return 'Observable';
}
if (is.array(value)) {
return 'Array';
}
if (is.buffer(value)) {
return 'Buffer';
}
const tagType = getObjectType(value);
if (tagType) {
return tagType;
}
if (value instanceof String || value instanceof Boolean || value instanceof Number) {
throw new TypeError('Please don\'t use object wrappers for primitive types');
}
return 'Object';
}
is.undefined = isOfType('undefined');
is.string = isOfType('string');
const isNumberType = isOfType('number');
is.number = (value: unknown): value is number => isNumberType(value) && !is.nan(value);
is.bigint = isOfType('bigint');
// eslint-disable-next-line @typescript-eslint/ban-types
is.function_ = isOfType('function');
is.null_ = (value: unknown): value is null => value === null;
is.class_ = (value: unknown): value is Class => is.function_(value) && value.toString().startsWith('class ');
is.boolean = (value: unknown): value is boolean => value === true || value === false;
is.symbol = isOfType('symbol');
is.numericString = (value: unknown): value is string =>
is.string(value) && !is.emptyStringOrWhitespace(value) && !Number.isNaN(Number(value));
is.array = Array.isArray;
is.buffer = (value: unknown): value is Buffer => (value as any)?.constructor?.isBuffer?.(value) ?? false;
is.nullOrUndefined = (value: unknown): value is null | undefined => is.null_(value) || is.undefined(value);
is.object = (value: unknown): value is object => !is.null_(value) && (typeof value === 'object' || is.function_(value));
is.iterable = (value: unknown): value is IterableIterator => is.function_((value as IterableIterator)?.[Symbol.iterator]);
is.asyncIterable = (value: unknown): value is AsyncIterableIterator => is.function_((value as AsyncIterableIterator)?.[Symbol.asyncIterator]);
is.generator = (value: unknown): value is Generator => is.iterable(value) && is.function_(value.next) && is.function_(value.throw);
is.asyncGenerator = (value: unknown): value is AsyncGenerator => is.asyncIterable(value) && is.function_(value.next) && is.function_(value.throw);
is.nativePromise = (value: unknown): value is Promise =>
isObjectOfType>('Promise')(value);
const hasPromiseAPI = (value: unknown): value is Promise =>
is.function_((value as Promise)?.then) &&
is.function_((value as Promise)?.catch);
is.promise = (value: unknown): value is Promise => is.nativePromise(value) || hasPromiseAPI(value);
is.generatorFunction = isObjectOfType('GeneratorFunction');
is.asyncGeneratorFunction = (value: unknown): value is ((...args: any[]) => Promise) => getObjectType(value) === 'AsyncGeneratorFunction';
is.asyncFunction = (value: unknown): value is ((...args: any[]) => Promise) => getObjectType(value) === 'AsyncFunction';
// eslint-disable-next-line no-prototype-builtins, @typescript-eslint/ban-types
is.boundFunction = (value: unknown): value is Function => is.function_(value) && !value.hasOwnProperty('prototype');
is.regExp = isObjectOfType('RegExp');
is.date = isObjectOfType('Date');
is.error = isObjectOfType('Error');
is.map = (value: unknown): value is Map => isObjectOfType