UNPKG

@danwithabox/nullish

Version:

Utilities that pair well with the lovely nullish coalescing (??) operator

99 lines (96 loc) 2.92 kB
/** * Map a nullish value as if it were non-nullish. * * The result retains either `null`, or `undefined`, or both, or neither, depending on what's inferred from the input value. * * Practically, the possible mappings are: * * --- * * `T | null | undefined` => `R | null | undefined` * ```ts * const val = 0 as number | null | undefined; * const res = nullishMap(val, val => `${val}`); * // ^ string | null | undefined * ``` * * --- * * `T | undefined` => `R | undefined` * ```ts * const val = 0 as number | undefined; * const res = nullishMap(val, val => `${val}`); * // ^ string | undefined * ``` * * --- * * `T | null` => `R | null` * ```ts * const val = 0 as number | null; * const res = nullishMap(val, val => `${val}`); * // ^ string | null * ``` * * --- * * `T` => `R` _(not terribly useful, but it's allowed for simplicity's sake)_ * ```ts * const val = 0 as number; * const res = nullishMap(val, val => `${val}`); * // ^ string * ``` * */ declare function nullishMap<T, R>(value: T, mapFn: (value: NonNullable<T>) => R): NullishMap<T, R>; /** * Union of `R`, and either `null`, `undefined`, or both, depending on which of the two are constituents of `T`. * * @see {@link nullishMap} */ type NullishMap<T, R> = T extends null ? null : T extends undefined ? undefined : R; /** * Augment a value's type with `null` and `undefined`. * * Zero performance impact at runtime, as it is simply an identity function, and it most likely gets inlined. * * Useful in a few common situations: * * --- * * Making an inferred type optional at variable declaration, since something like https://github.com/microsoft/TypeScript/issues/13321 is not yet possible: * ```ts * let optional = nullishOf({ foo: 1, bar: 2, }) ?? void 0; * // ^ { foo: number; bar: number; } | undefined * ``` * --- * Safely accessing arrays without enabling `noUncheckedIndexedAccess` in `tsconfig.json`: * ```ts * const myArray = [0, , 2].map(n => Boolean(n)); * * // Without `noUncheckedIndexedAccess`: * let element = myArray[1]; * // ^ `boolean` * // this is incorrect, due to the empty element * * // With manual typing: * let maybeElement1 = myArray[1] as undefined | (typeof myArray)[number]; * // ^ `boolean | undefined` * // correct, but a hassle to type * * // With `nullishOf`: * let maybeElement2 = nullishOf(myArray[1]); * // ^ `boolean | null | undefined` * // correct enough: it has an extraneous `null`, but that's fine in most situations * * // And if you want to narrow to either `null` or `undefined`: * let maybeElement3 = nullishOf(myArray[1]) ?? null; * // ^ `boolean | null` * // correct * let maybeElement4 = nullishOf(myArray[1]) ?? void 0; * // ^ `boolean | undefined` * // correct * ``` */ declare function nullishOf<T>(value: T): T | null | undefined; export { type NullishMap, nullishMap, nullishOf };