Require Node.js 18

This commit is contained in:
Sindre Sorhus 2024-07-10 15:41:12 +02:00
parent 25a376875d
commit 0ff273fee8
7 changed files with 56 additions and 40 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
node_modules node_modules
yarn.lock yarn.lock
dist /distribution
.tsimp .tsimp

View file

@ -11,19 +11,21 @@
"url": "https://sindresorhus.com" "url": "https://sindresorhus.com"
}, },
"type": "module", "type": "module",
"exports": "./dist/index.js", "exports": {
"types": "./dist/index.d.ts", "types": "./distribution/index.d.ts",
"default": "./distribution/index.js"
},
"sideEffects": false, "sideEffects": false,
"engines": { "engines": {
"node": ">=16" "node": ">=18"
}, },
"scripts": { "scripts": {
"build": "del dist && tsc", "build": "del distribution && tsc",
"test": "tsc --noEmit && xo && ava", "test": "tsc --noEmit && xo && ava",
"prepare": "npm run build" "prepare": "npm run build"
}, },
"files": [ "files": [
"dist" "distribution"
], ],
"keywords": [ "keywords": [
"type", "type",
@ -50,19 +52,19 @@
"types" "types"
], ],
"devDependencies": { "devDependencies": {
"@sindresorhus/tsconfig": "^5.0.0", "@sindresorhus/tsconfig": "^6.0.0",
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/node": "^20.14.8", "@types/node": "^20.14.10",
"@types/zen-observable": "^0.8.3", "@types/zen-observable": "^0.8.7",
"ava": "^6.1.3", "ava": "^6.1.3",
"del-cli": "^5.0.0", "del-cli": "^5.1.0",
"expect-type": "^0.16.0", "expect-type": "^0.19.0",
"jsdom": "^22.1.0", "jsdom": "^24.1.0",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"tempy": "^3.1.0", "tempy": "^3.1.0",
"tsimp": "^2.0.11", "tsimp": "^2.0.11",
"typescript": "^5.1.6", "typescript": "^5.5.3",
"xo": "^0.56.0", "xo": "^0.58.0",
"zen-observable": "^0.10.0" "zen-observable": "^0.10.0"
}, },
"ava": { "ava": {

View file

@ -133,6 +133,10 @@ is.array(value, is.number); // Validate `value` is an array and all of its items
##### .function(value) ##### .function(value)
##### .buffer(value) ##### .buffer(value)
> [!NOTE]
> [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer)
##### .blob(value) ##### .blob(value)
##### .object(value) ##### .object(value)

View file

@ -1,4 +1,3 @@
import type {Buffer} from 'node:buffer';
import type { import type {
ArrayLike, ArrayLike,
Class, Class,
@ -13,6 +12,14 @@ import type {
Whitespace, Whitespace,
} from './types.js'; } from './types.js';
// From type-fest.
type ExtractFromGlobalConstructors<Name extends string> =
Name extends string
? typeof globalThis extends Record<Name, new (...arguments_: any[]) => infer T> ? T : never
: never;
type NodeBuffer = ExtractFromGlobalConstructors<'Buffer'>;
const typedArrayTypeNames = [ const typedArrayTypeNames = [
'Int8Array', 'Int8Array',
'Uint8Array', 'Uint8Array',
@ -314,7 +321,7 @@ const is = Object.assign(
}, },
); );
function isAbsoluteMod2(remainder: 0 | 1) { function isAbsoluteModule2(remainder: 0 | 1) {
return (value: unknown): value is number => isInteger(value) && Math.abs(value % 2) === remainder; return (value: unknown): value is number => isInteger(value) && Math.abs(value % 2) === remainder;
} }
@ -350,7 +357,7 @@ export function isArrayLike<T = unknown>(value: unknown): value is ArrayLike<T>
return !isNullOrUndefined(value) && !isFunction(value) && isValidLength((value as ArrayLike<T>).length); return !isNullOrUndefined(value) && !isFunction(value) && isValidLength((value as ArrayLike<T>).length);
} }
export function isAsyncFunction<T = unknown>(value: unknown): value is ((...args: any[]) => Promise<T>) { export function isAsyncFunction<T = unknown>(value: unknown): value is ((...arguments_: any[]) => Promise<T>) {
return getObjectType(value) === 'AsyncFunction'; return getObjectType(value) === 'AsyncFunction';
} }
@ -358,7 +365,7 @@ export function isAsyncGenerator(value: unknown): value is AsyncGenerator {
return isAsyncIterable(value) && isFunction((value as AsyncGenerator).next) && isFunction((value as AsyncGenerator).throw); return isAsyncIterable(value) && isFunction((value as AsyncGenerator).next) && isFunction((value as AsyncGenerator).throw);
} }
export function isAsyncGeneratorFunction(value: unknown): value is ((...args: any[]) => Promise<unknown>) { export function isAsyncGeneratorFunction(value: unknown): value is ((...arguments_: any[]) => Promise<unknown>) {
return getObjectType(value) === 'AsyncGeneratorFunction'; return getObjectType(value) === 'AsyncGeneratorFunction';
} }
@ -388,10 +395,13 @@ export function isBoolean(value: unknown): value is boolean {
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
export function isBoundFunction(value: unknown): value is Function { export function isBoundFunction(value: unknown): value is Function {
return isFunction(value) && !Object.prototype.hasOwnProperty.call(value, 'prototype'); return isFunction(value) && !Object.hasOwn(value, 'prototype');
} }
export function isBuffer(value: unknown): value is Buffer { /**
Note: [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer)
*/
export function isBuffer(value: unknown): value is NodeBuffer {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
return (value as any)?.constructor?.isBuffer?.(value) ?? false; return (value as any)?.constructor?.isBuffer?.(value) ?? false;
} }
@ -450,7 +460,7 @@ export function isError(value: unknown): value is Error {
} }
export function isEvenInteger(value: unknown): value is number { export function isEvenInteger(value: unknown): value is number {
return isAbsoluteMod2(0)(value); return isAbsoluteModule2(0)(value);
} }
// Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);` // Example: `is.falsy = (value: unknown): value is (not true | 0 | '' | undefined | null) => Boolean(value);`
@ -629,7 +639,7 @@ export function isObservable(value: unknown): value is ObservableLike {
} }
export function isOddInteger(value: unknown): value is number { export function isOddInteger(value: unknown): value is number {
return isAbsoluteMod2(1)(value); return isAbsoluteModule2(1)(value);
} }
export function isPlainObject<Value = unknown>(value: unknown): value is Record<PropertyKey, Value> { export function isPlainObject<Value = unknown>(value: unknown): value is Record<PropertyKey, Value> {
@ -768,7 +778,7 @@ export function isWeakMap<Key extends object = object, Value = unknown>(value: u
return getObjectType(value) === 'WeakMap'; return getObjectType(value) === 'WeakMap';
} }
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types, unicorn/prevent-abbreviations
export function isWeakRef(value: unknown): value is WeakRef<object> { export function isWeakRef(value: unknown): value is WeakRef<object> {
return getObjectType(value) === 'WeakRef'; return getObjectType(value) === 'WeakRef';
} }
@ -782,7 +792,7 @@ export function isWhitespaceString(value: unknown): value is Whitespace {
return isString(value) && /^\s+$/.test(value); return isString(value) && /^\s+$/.test(value);
} }
type ArrayMethod = (fn: (value: unknown, index: number, array: unknown[]) => boolean, thisArg?: unknown) => boolean; type ArrayMethod = (function_: (value: unknown, index: number, array: unknown[]) => boolean, thisArgument?: unknown) => boolean;
function predicateOnArray(method: ArrayMethod, predicate: Predicate, values: unknown[]) { function predicateOnArray(method: ArrayMethod, predicate: Predicate, values: unknown[]) {
if (!isFunction(predicate)) { if (!isFunction(predicate)) {
@ -832,7 +842,7 @@ type Assert = {
symbol: (value: unknown, message?: string) => asserts value is symbol; symbol: (value: unknown, message?: string) => asserts value is symbol;
numericString: (value: unknown, message?: string) => asserts value is `${number}`; numericString: (value: unknown, message?: string) => asserts value is `${number}`;
array: <T = unknown>(value: unknown, assertion?: (element: unknown) => asserts element is T, message?: string) => asserts value is T[]; array: <T = unknown>(value: unknown, assertion?: (element: unknown) => asserts element is T, message?: string) => asserts value is T[];
buffer: (value: unknown, message?: string) => asserts value is Buffer; buffer: (value: unknown, message?: string) => asserts value is NodeBuffer;
blob: (value: unknown, message?: string) => asserts value is Blob; blob: (value: unknown, message?: string) => asserts value is Blob;
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
nullOrUndefined: (value: unknown, message?: string) => asserts value is null | undefined; nullOrUndefined: (value: unknown, message?: string) => asserts value is null | undefined;
@ -1218,7 +1228,10 @@ export function assertBoundFunction(value: unknown, message?: string): asserts v
} }
} }
export function assertBuffer(value: unknown, message?: string): asserts value is Buffer { /**
Note: [Prefer using `Uint8Array` instead of `Buffer`.](https://sindresorhus.com/blog/goodbye-nodejs-buffer)
*/
export function assertBuffer(value: unknown, message?: string): asserts value is NodeBuffer {
if (!isBuffer(value)) { if (!isBuffer(value)) {
throw new TypeError(message ?? typeErrorMessage('Buffer', value)); throw new TypeError(message ?? typeErrorMessage('Buffer', value));
} }
@ -1656,7 +1669,7 @@ export function assertWeakMap<Key extends object = object, Value = unknown>(valu
} }
} }
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types, unicorn/prevent-abbreviations
export function assertWeakRef<T extends object = object>(value: unknown, message?: string): asserts value is WeakRef<T> { export function assertWeakRef<T extends object = object>(value: unknown, message?: string): asserts value is WeakRef<T> {
if (!isWeakRef(value)) { if (!isWeakRef(value)) {
throw new TypeError(message ?? typeErrorMessage('WeakRef', value)); throw new TypeError(message ?? typeErrorMessage('WeakRef', value));

View file

@ -56,7 +56,7 @@ export type ObservableLike = {
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
export type Falsy = false | 0 | 0n | '' | null | undefined; export type Falsy = false | 0 | 0n | '' | null | undefined;
export type WeakRef<T extends object> = { // eslint-disable-line @typescript-eslint/ban-types export type WeakRef<T extends object> = { // eslint-disable-line @typescript-eslint/ban-types, unicorn/prevent-abbreviations
readonly [Symbol.toStringTag]: 'WeakRef'; readonly [Symbol.toStringTag]: 'WeakRef';
deref(): T | undefined; deref(): T | undefined;
}; };

View file

@ -27,18 +27,18 @@ const {document} = window;
const structuredClone = globalThis.structuredClone ?? (x => x); const structuredClone = globalThis.structuredClone ?? (x => x);
type Test = { type Test = {
assert: (...args: any[]) => void | never; assert: (...arguments_: any[]) => void | never;
fixtures: unknown[]; fixtures: unknown[];
typename?: TypeName; typename?: TypeName;
typeDescription?: AssertionTypeDescription; typeDescription?: AssertionTypeDescription;
is(value: unknown): boolean; is(value: unknown): boolean;
}; };
const invertAssertThrow = (description: AssertionTypeDescription, fn: () => void | never, value: unknown): void | never => { const invertAssertThrow = (description: AssertionTypeDescription, function_: () => void | never, value: unknown): void | never => {
const expectedAssertErrorMessage = `Expected value which is \`${description}\`, received value of type \`${is(value)}\`.`; const expectedAssertErrorMessage = `Expected value which is \`${description}\`, received value of type \`${is(value)}\`.`;
try { try {
fn(); function_();
} catch (error: unknown) { } catch (error: unknown) {
if (error instanceof TypeError && error.message.includes(expectedAssertErrorMessage)) { if (error instanceof TypeError && error.message.includes(expectedAssertErrorMessage)) {
return; return;
@ -488,10 +488,10 @@ const types = new Map<string, Test>([
fixtures: [ fixtures: [
{x: 1}, {x: 1},
Object.create(null), Object.create(null),
new Object(), // eslint-disable-line no-new-object new Object(), // eslint-disable-line no-object-constructor
structuredClone({x: 1}), structuredClone({x: 1}),
structuredClone(Object.create(null)), structuredClone(Object.create(null)),
structuredClone(new Object()), // eslint-disable-line no-new-object structuredClone(new Object()), // eslint-disable-line no-object-constructor
], ],
typename: 'Object', typename: 'Object',
typeDescription: 'plain object', typeDescription: 'plain object',
@ -1841,14 +1841,14 @@ test('is.nonEmptyStringAndNotWhitespace', t => {
test('is.emptyObject', t => { test('is.emptyObject', t => {
t.true(is.emptyObject({})); t.true(is.emptyObject({}));
t.true(is.emptyObject(new Object())); // eslint-disable-line no-new-object t.true(is.emptyObject(new Object())); // eslint-disable-line no-object-constructor
t.false(is.emptyObject({unicorn: '🦄'})); t.false(is.emptyObject({unicorn: '🦄'}));
t.notThrows(() => { t.notThrows(() => {
assert.emptyObject({}); assert.emptyObject({});
}); });
t.notThrows(() => { t.notThrows(() => {
assert.emptyObject(new Object()); // eslint-disable-line no-new-object assert.emptyObject(new Object()); // eslint-disable-line no-object-constructor
}); });
t.throws(() => { t.throws(() => {
assert.emptyObject({unicorn: '🦄'}); assert.emptyObject({unicorn: '🦄'});
@ -1860,14 +1860,14 @@ test('is.nonEmptyObject', t => {
is.nonEmptyObject(foo); is.nonEmptyObject(foo);
t.false(is.nonEmptyObject({})); t.false(is.nonEmptyObject({}));
t.false(is.nonEmptyObject(new Object())); // eslint-disable-line no-new-object t.false(is.nonEmptyObject(new Object())); // eslint-disable-line no-object-constructor
t.true(is.nonEmptyObject({unicorn: '🦄'})); t.true(is.nonEmptyObject({unicorn: '🦄'}));
t.throws(() => { t.throws(() => {
assert.nonEmptyObject({}); assert.nonEmptyObject({});
}); });
t.throws(() => { t.throws(() => {
assert.nonEmptyObject(new Object()); // eslint-disable-line no-new-object assert.nonEmptyObject(new Object()); // eslint-disable-line no-object-constructor
}); });
t.notThrows(() => { t.notThrows(() => {
assert.nonEmptyObject({unicorn: '🦄'}); assert.nonEmptyObject({unicorn: '🦄'});

View file

@ -1,8 +1,5 @@
{ {
"extends": "@sindresorhus/tsconfig", "extends": "@sindresorhus/tsconfig",
"compilerOptions": {
"outDir": "dist",
},
"include": [ "include": [
"source" "source"
], ],