# @wistia/type-guards — full reference

Runtime type guards and utility types for TypeScript. Every guard is a
`value is T` predicate that narrows `unknown` values; every type is a
small composable building block. Side-effect free, tree-shakeable, ESM
and CJS builds.

## Install

```sh
npm install @wistia/type-guards
yarn add @wistia/type-guards
pnpm add @wistia/type-guards
```

## Import

```ts
import {
  isString,
  isNotNil,
  isNonEmptyArray,
  type Nilable,
  type NonEmptyArray,
} from '@wistia/type-guards';
```

## Guards

<!-- AUTOGEN:LLMS-FULL-GUARDS:START -->
### `hasKey`

```ts
hasKey<Key extends string, Value>(value: unknown, key: Key): value is Record<Key, Value>
```

```ts
hasKey({ a: 1 }, 'a'); // true
hasKey({ a: 1 }, 'b'); // false
```

### `isArray`

```ts
isArray(value: unknown): value is unknown[]
```

```ts
isArray([1, 2]); // true
isArray('abc');  // false
```

### `isBoolean`

```ts
isBoolean(value: unknown): value is boolean
```

```ts
isBoolean(true); // true
isBoolean(1);    // false
```

### `isDate`

```ts
isDate(value: unknown): value is Date
```

Matches `Date` instances only. Does not parse date strings or
accept numeric timestamps.

```ts
isDate(new Date());   // true
isDate('2024-01-01'); // false
```

### `isEmptyArray`

```ts
isEmptyArray(value: unknown): value is never[]
```

```ts
isEmptyArray([]);  // true
isEmptyArray([1]); // false
```

### `isEmptyRecord`

```ts
isEmptyRecord(value: unknown): value is EmptyObject
```

```ts
isEmptyRecord({});       // true
isEmptyRecord({ a: 1 }); // false
```

### `isEmptyString`

```ts
isEmptyString(value: unknown): value is ''
```

```ts
isEmptyString('');  // true
isEmptyString('a'); // false
```

### `isError`

```ts
isError(value: unknown): value is Error
```

Matches subclasses of `Error` too (e.g. `TypeError`, custom errors).

```ts
isError(new Error('boom')); // true
isError('boom');            // false
```

### `isFalsy`

```ts
isFalsy(value: unknown): value is Falsy
```

Returns true for `false`, `0`, `-0`, `0n`, `''`, `null`, `undefined`,
and `NaN`.

```ts
isFalsy(0); // true
isFalsy(1); // false
```

### `isFunction`

```ts
isFunction(value: unknown): value is (...args: unknown[]) => unknown
```

```ts
isFunction(() => {}); // true
isFunction({});       // false
```

### `isInteger`

```ts
isInteger(value: unknown): value is number
```

Uses `Number.isInteger`, so non-finite values (`NaN`, `Infinity`)
return false.

```ts
isInteger(5);   // true
isInteger(5.5); // false
```

### `isNaN`

```ts
isNaN(value: unknown): value is number
```

Uses `Number.isNaN` (not the coercive global `isNaN`), so only the
literal `NaN` value returns true.

```ts
isNaN(Number.NaN); // true
isNaN(0);          // false
```

### `isNil`

```ts
isNil(value: unknown): value is Nil
```

```ts
isNil(null); // true
isNil(0);    // false
```

### `isNonEmptyArray`

```ts
isNonEmptyArray<T>(value: Nilable<T[] | UnknownRecord>): value is NonEmptyArray<T>
```

```ts
isNonEmptyArray([1]); // true
isNonEmptyArray([]);  // false
```

### `isNonEmptyRecord`

```ts
isNonEmptyRecord(value: unknown): value is Record<string, unknown>
```

```ts
isNonEmptyRecord({ a: 1 }); // true
isNonEmptyRecord({});       // false
```

### `isNonEmptyString`

```ts
isNonEmptyString(value: unknown): value is string
```

```ts
isNonEmptyString('a'); // true
isNonEmptyString('');  // false
```

### `isNotArray`

```ts
isNotArray(value: unknown): value is Exclude<unknown, unknown[]>
```

```ts
isNotArray('x'); // true
isNotArray([]);  // false
```

### `isNotBoolean`

```ts
isNotBoolean(value: unknown): value is Exclude<unknown, boolean>
```

```ts
isNotBoolean(1);    // true
isNotBoolean(true); // false
```

### `isNotFunction`

```ts
isNotFunction(value: unknown): value is Exclude<unknown, (...args: unknown[]) => unknown>
```

```ts
isNotFunction(1);        // true
isNotFunction(() => {}); // false
```

### `isNotNil`

```ts
isNotNil<T>(value: Nil | T): value is T
```

Common in `.filter(isNotNil)` to drop `null`/`undefined` from arrays
with narrowing.

```ts
isNotNil(0);    // true
isNotNil(null); // false

const items: (string | null)[] = ['a', null, 'b'];
const clean: string[] = items.filter(isNotNil); // ['a', 'b']
```

### `isNotNull`

```ts
isNotNull<T>(value: unknown): value is Exclude<T, null>
```

```ts
isNotNull(undefined); // true
isNotNull(null);      // false
```

### `isNotNumber`

```ts
isNotNumber(value: unknown): value is Exclude<unknown, number>
```

```ts
isNotNumber('1'); // true
isNotNumber(1);   // false
```

### `isNotRecord`

```ts
isNotRecord(value: unknown): value is Exclude<unknown, EmptyObject | Record<string, unknown>>
```

```ts
isNotRecord([]); // true
isNotRecord({}); // false
```

### `isNotString`

```ts
isNotString(value: unknown): value is Exclude<unknown, string>
```

```ts
isNotString(1);   // true
isNotString('a'); // false
```

### `isNotUndefined`

```ts
isNotUndefined<T>(value: Undefinable<T>): value is Exclude<T, undefined>
```

```ts
isNotUndefined(null);      // true
isNotUndefined(undefined); // false
```

### `isNotVoid`

```ts
isNotVoid(value: unknown): value is Exclude<unknown, void>
```

```ts
isNotVoid(0);         // true
isNotVoid(undefined); // false
```

### `isNull`

```ts
isNull(value: unknown): value is null
```

```ts
isNull(null);      // true
isNull(undefined); // false
```

### `isNumber`

```ts
isNumber(value: unknown): value is number
```

`NaN` is a `number`, so `isNumber(NaN)` is true. Use `isInteger` or
combine with `!isNaN(value)` if you need a finite number.

```ts
isNumber(1);   // true
isNumber('1'); // false
```

### `isRecord`

```ts
isRecord(value: unknown): value is EmptyObject | Record<string, unknown>
```

```ts
isRecord({}); // true
isRecord([]); // false
```

### `isString`

```ts
isString(value: unknown): value is string
```

```ts
isString('hi'); // true
isString(42);   // false
```

### `isTruthy`

```ts
isTruthy(value: unknown): boolean
```

The complement of `isFalsy`. Does not provide narrowing on its own;
use `isNotNil` or a specific positive guard when narrowing matters.

```ts
isTruthy(1); // true
isTruthy(0); // false
```

### `isUndefined`

```ts
isUndefined(value: unknown): value is undefined
```

```ts
isUndefined(undefined); // true
isUndefined(null);      // false
```

### `isVoid`

```ts
isVoid(value: unknown): value is void
```

```ts
isVoid(undefined); // true
isVoid(0);         // false
```
<!-- AUTOGEN:LLMS-FULL-GUARDS:END -->

## Types

<!-- AUTOGEN:LLMS-FULL-TYPES:START -->
### `Arrayable<T>`

```ts
type Arrayable<T> = T | T[];
type Tags = Arrayable<string>; // string | string[]
```

### `Falsy`

```ts
type Falsy = typeof Number.NaN | '' | 0n | false | null | undefined;
type X = Falsy; // number | '' | 0n | false | null | undefined
```

### `NestedNonNullable<T, P extends Paths<T> & string>`

```ts
type NestedNonNullable<T, P extends Paths<T> & string> = NonNullable<Get<T, P>>;
type User = { profile?: { name?: string } };
type Name = NestedNonNullable<User, 'profile.name'>; // string
```

This type recursively traverses the object along the given path and applies `NonNullable` to the resulting type.
It may fail for excessively deep property paths or in the presence of circular references. In such cases, consider
using nested `NonNullable` definitions to avoid errors such as:
- TS2589: Type instantiation is excessively deep and possibly infinite.
- TS2615: Type of property 'XYZ' circularly references itself in mapped type.

### `Nil`

```ts
type Nil = null | undefined;
type X = Nil; // null | undefined
```

### `Nilable<A>`

```ts
type Nilable<A> = A | Nil;
type Maybe = Nilable<string>; // string | null | undefined
```

### `NilableArray<T>`

```ts
type NilableArray<T> = Nilable<Nilable<T>[]>;
type Items = NilableArray<string>; // (string | null | undefined)[] | null | undefined
```

### `NonEmptyArray<T>`

```ts
type NonEmptyArray<T> = [T, ...T[]];
type Ids = NonEmptyArray<number>; // [number, ...number[]]
```

### `NotNilable<A>`

```ts
type NotNilable<A> = Exclude<A, Nil>;
type X = NotNilable<string | null | undefined>; // string
```

### `Nullable<A>`

```ts
type Nullable<A> = A | null;
type X = Nullable<string>; // string | null
```

### `NullableProperties<T extends UnknownRecord>`

```ts
type NullableProperties<T extends UnknownRecord> = { [Key in keyof T]: Nullable<T[Key]> };
type User = { name: string; age: number };
type X = NullableProperties<User>; // { name: string | null; age: number | null }
```

### `Truthy<T>`

```ts
type Truthy<T> = Exclude<T, Falsy>;
type X = Truthy<string | 0 | null>; // string
```

### `Undefinable<A>`

```ts
type Undefinable<A> = A | undefined;
type X = Undefinable<string>; // string | undefined
```
<!-- AUTOGEN:LLMS-FULL-TYPES:END -->

## Patterns

Filter out nullish values from a list, with narrowing:

```ts
import { isNotNil } from '@wistia/type-guards';

const raw: (string | null | undefined)[] = ['a', null, 'b', undefined];
const clean: string[] = raw.filter(isNotNil); // ['a', 'b']
```

Narrow a parameter before using it:

```ts
import { isString, isNonEmptyArray } from '@wistia/type-guards';

function describe(value: unknown): string {
  if (isString(value)) return value.toUpperCase();
  if (isNonEmptyArray<unknown>(value)) return `${value.length} items`;
  return 'other';
}
```

Safely access an unknown object key:

```ts
import { hasKey } from '@wistia/type-guards';

function readName(value: unknown): string | undefined {
  if (hasKey<'name', string>(value, 'name') && typeof value.name === 'string') {
    return value.name;
  }
  return undefined;
}
```
