Type check values with comprehensive TypeScript type guards and runtime assertions
—
Multi-value validation, logical operations, and specialized validation patterns including predicate testing, enum checking, and truthiness validation.
Check multiple values against predicates for comprehensive validation.
/**
* Check if all values pass the predicate
* @param predicate - Function to test each value
* @param values - Values to test
* @returns True if all values pass predicate
*/
function isAll(predicate: Predicate, ...values: unknown[]): boolean;
/**
* Check if any value passes any of the predicates
* @param predicate - Single predicate or array of predicates
* @param values - Values to test
* @returns True if any value passes any predicate
*/
function isAny(predicate: Predicate | Predicate[], ...values: unknown[]): boolean;
type Predicate = (value: unknown) => boolean;Usage Examples:
import is from '@sindresorhus/is';
// Test all values against single predicate
is.all(is.string, 'hello', 'world', 'test'); // => true
is.all(is.string, 'hello', 42, 'test'); // => false
is.all(is.number, 1, 2, 3, 4); // => true
// Test any value against single predicate
is.any(is.string, 42, true, 'hello'); // => true
is.any(is.string, 42, true, null); // => false
// Test any value against multiple predicates
is.any([is.string, is.number], {}, true, 'hello'); // => true (string matches)
is.any([is.boolean, is.number], 'hello', [], {}); // => false
// Practical usage
function validateUserData(name: unknown, age: unknown, email: unknown) {
if (!is.all(is.string, name, email)) {
throw new Error('Name and email must be strings');
}
if (!is.number(age)) {
throw new Error('Age must be a number');
}
return { name, age, email };
}
// Flexible validation
function hasValidId(data: unknown[]) {
// Accept either string or number IDs
return is.any([is.string, is.number], ...data);
}Check logical truthiness and falsiness of values.
/**
* Check if value is truthy
* @param value - Value to check
* @returns True if value is truthy
*/
function isTruthy<T>(value: T | Falsy): value is T;
/**
* Check if value is falsy
* @param value - Value to check
* @returns True if value is falsy
*/
function isFalsy(value: unknown): value is Falsy;
type Falsy = false | 0 | 0n | '' | null | undefined;Usage Examples:
import is from '@sindresorhus/is';
// Truthy values
is.truthy('hello'); // => true
is.truthy(42); // => true
is.truthy([]); // => true (arrays are truthy)
is.truthy({}); // => true (objects are truthy)
// Falsy values
is.falsy(false); // => true
is.falsy(0); // => true
is.falsy(0n); // => true
is.falsy(''); // => true
is.falsy(null); // => true
is.falsy(undefined); // => true
is.falsy('0'); // => false (string '0' is truthy)
is.falsy([]); // => false (empty array is truthy)
// Type guard usage
function processValue<T>(value: T | null | undefined) {
if (is.truthy(value)) {
// value is now typed as T (non-falsy)
return value.toString();
}
return 'No value provided';
}
// Filtering arrays
const mixedArray = ['hello', '', 0, 'world', null, 42, false];
const truthyValues = mixedArray.filter(is.truthy);
console.log(truthyValues); // ['hello', 'world', 42]
const falsyValues = mixedArray.filter(is.falsy);
console.log(falsyValues); // ['', 0, null, false]Check if a value is a member of a TypeScript enum.
/**
* Check if value is a member of the given enum
* @param value - Value to check
* @param targetEnum - Enum to check against
* @returns True if value is enum member
*/
function isEnumCase<T = unknown>(value: unknown, targetEnum: T): value is T[keyof T];Usage Examples:
import is from '@sindresorhus/is';
enum Direction {
Up = 'up',
Down = 'down',
Left = 'left',
Right = 'right'
}
enum Status {
Pending = 0,
Approved = 1,
Rejected = 2
}
is.enumCase('up', Direction); // => true
is.enumCase('diagonal', Direction); // => false
is.enumCase(1, Status); // => true
is.enumCase(3, Status); // => false
// Type guard usage
function processDirection(input: unknown) {
if (is.enumCase(input, Direction)) {
// input is now typed as Direction
switch (input) {
case Direction.Up:
return 'Moving up';
case Direction.Down:
return 'Moving down';
case Direction.Left:
return 'Moving left';
case Direction.Right:
return 'Moving right';
}
}
throw new Error('Invalid direction');
}
// API response validation
function validateStatus(response: { status: unknown }) {
if (is.enumCase(response.status, Status)) {
return response.status; // Typed as Status
}
throw new Error('Invalid status in response');
}Check if an instance is a direct instance of a class (not inherited).
/**
* Check if instance is direct instance of class (not inherited)
* @param instance - Instance to check
* @param class_ - Class constructor to check against
* @returns True if instance is direct instance
*/
function isDirectInstanceOf<T>(instance: unknown, class_: Class<T>): instance is T;
type Class<T, Arguments extends unknown[] = any[]> = Constructor<T, Arguments> & {prototype: T};Usage Examples:
import is from '@sindresorhus/is';
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}
}
const animal = new Animal('Generic');
const dog = new Dog('Buddy', 'Golden Retriever');
// Direct instance checking
is.directInstanceOf(animal, Animal); // => true
is.directInstanceOf(dog, Animal); // => false (inherited, not direct)
is.directInstanceOf(dog, Dog); // => true
// Compare with regular instanceof
console.log(dog instanceof Animal); // => true (inheritance chain)
console.log(is.directInstanceOf(dog, Animal)); // => false (direct only)
// Type guard usage
function processAnimal(animal: unknown) {
if (is.directInstanceOf(animal, Animal)) {
// animal is typed as Animal (not subclass)
console.log('Processing base animal:', animal.name);
} else if (is.directInstanceOf(animal, Dog)) {
// animal is typed as Dog
console.log('Processing dog:', animal.name, animal.breed);
}
}Check if a value can be used as an object property key.
/**
* Check if value can be used as object property key
* @param value - Value to check
* @returns True if value is valid property key
*/
function isPropertyKey(value: unknown): value is PropertyKey;
type PropertyKey = string | number | symbol;Usage Examples:
import is from '@sindresorhus/is';
is.propertyKey('key'); // => true
is.propertyKey(42); // => true
is.propertyKey(Symbol('key')); // => true
is.propertyKey({}); // => false
is.propertyKey(null); // => false
is.propertyKey(true); // => false
// Type guard usage
function safeObjectAccess(obj: Record<PropertyKey, unknown>, key: unknown) {
if (is.propertyKey(key)) {
// key is now typed as PropertyKey
return obj[key];
}
throw new Error('Invalid property key');
}
// Dynamic property setting
function setProperty(obj: object, key: unknown, value: unknown) {
if (is.propertyKey(key)) {
(obj as any)[key] = value;
return true;
}
return false;
}
// Object key filtering
function filterValidKeys(keys: unknown[]): PropertyKey[] {
return keys.filter(is.propertyKey);
}import is from '@sindresorhus/is';
function validateBatch<T>(
values: unknown[],
predicate: (value: unknown) => value is T
): T[] {
if (!is.all(predicate, ...values)) {
throw new Error('All values must pass validation');
}
return values as T[];
}
// Usage
const stringArray = validateBatch(['a', 'b', 'c'], is.string);
const numberArray = validateBatch([1, 2, 3], is.number);
function validateMixedTypes(values: unknown[]) {
const hasStrings = is.any(is.string, ...values);
const hasNumbers = is.any(is.number, ...values);
return {
hasStrings,
hasNumbers,
isHomogeneous: is.all(is.string, ...values) || is.all(is.number, ...values)
};
}import is from '@sindresorhus/is';
enum LogLevel {
Debug = 'debug',
Info = 'info',
Warn = 'warn',
Error = 'error'
}
interface Config {
host: string;
port: number;
logLevel: LogLevel;
features: string[];
}
function validateConfig(config: Record<string, unknown>): Config {
// Required string fields
if (!is.all(is.string, config.host)) {
throw new Error('Host must be a string');
}
// Port validation
if (!is.number(config.port) || config.port <= 0) {
throw new Error('Port must be a positive number');
}
// Enum validation
if (!is.enumCase(config.logLevel, LogLevel)) {
throw new Error('Invalid log level');
}
// Array validation
if (!is.array(config.features, is.string)) {
throw new Error('Features must be array of strings');
}
return config as Config;
}import is from '@sindresorhus/is';
function partitionArray<T>(
array: unknown[],
predicate: (value: unknown) => value is T
): [T[], unknown[]] {
const matching: T[] = [];
const nonMatching: unknown[] = [];
for (const item of array) {
if (predicate(item)) {
matching.push(item);
} else {
nonMatching.push(item);
}
}
return [matching, nonMatching];
}
// Usage
const mixedData = ['hello', 42, true, 'world', null, 3.14];
const [strings, nonStrings] = partitionArray(mixedData, is.string);
const [numbers, nonNumbers] = partitionArray(nonStrings, is.number);
console.log('Strings:', strings); // ['hello', 'world']
console.log('Numbers:', numbers); // [42, 3.14]import is from '@sindresorhus/is';
function acceptMultipleTypes(value: unknown): string {
if (is.any([is.string, is.number, is.boolean], value)) {
return String(value);
}
if (is.any([is.array, is.plainObject], value)) {
return JSON.stringify(value);
}
return 'Unknown type';
}
function requireAllFields(data: Record<string, unknown>, ...fields: string[]) {
const values = fields.map(field => data[field]);
if (!is.all(is.truthy, ...values)) {
throw new Error(`Missing required fields: ${fields.join(', ')}`);
}
return data;
}isAll() requires all values to pass the predicate; fails fast on first failureisAny() with single predicate tests if any value passes; with array tests if any value passes any predicateisTruthy() and isFalsy() follow JavaScript truthiness rules exactlyisEnumCase() works with both string and numeric enumsisDirectInstanceOf() checks prototype chain directly, not inheritanceisPropertyKey() validates JavaScript property key types (string, number, symbol)Install with Tessl CLI
npx tessl i tessl/npm-sindresorhus--is