Options
All
  • Public
  • Public/Protected
  • All
Menu

Types and tools for Salesforce TypeScript development

What is this?

This is a simple TypeScript-oriented library developed for use in Salesforce TypeScript libraries, applications, and plugins consisting of two parts:

  1. A collection of commonly desired types.
  2. A collection of type-narrowing convenience functions for writing concise type-guards.

See the API documentation for more details on each of the utilities that ts-types provides.

Why did we create it?

We were interested in developing with strict compiler settings in TypeScript. Among the sub-settings that comprise strict mode are strictNullChecks, strictPropertyInitialization, and noImplicitAny. tslint provides additional rules that further improve code quality and type correctness by discouraging explicit any usages and other unsafe constructs such as some classes of unwarranted type assertions. Together, these settings have the potential to increase code quality substantially, reducing the frequency of certain classes of runtime errors typical in classical JavaScript applications. They also encourage the writing of clearer, more accurately typed code, which helps teams work together more effectively and more rapidly onboard new hires.

Of course, stricter compiler settings require developers to write more type-safe code -- or to work around the compiler's insistence on type-safety. Often this stricter style leads to more verbose code in the way of type declarations and type guards, and can require new and occasionally unfamiliar patterns to accomplish without subverting the compiler's enforcement of the type system (typically via the use of type assertions).

TypeScript provides both syntax and built-in types designed to help write well-typed code, but we can be more terse and concise by employing additional types and type-narrowing utility functions by leveraging language features like type predicates backed by sound runtime validation, simplified undefined and null checking, etc. That's where this library comes in.

How will it help me?

This library has its roots in solving the problem of how to handle untyped JSON data in a type-safe way. It was born when we added some basic type declarations to replace the unsafe any type as a stand-in for JSON data with a type that could capture the range of data available in any JSON construct. This yielded the AnyJson type, which is effectively a union of all primitive and collection JSON values. The type alone was not enough to make for convenient, type-guarded handling of JSON data, however. TypeScript supports a very elegant system of control flow analysis that will narrow the type of a variable in code after the compiler can prove the set of possible types of the variable has been reduced. Using type guards in your code improves its runtime type safety characteristics, makes it more readable, and provides richer typing information for IDEs. Type guards are implemented as conditional statements, however, and can quickly become noisy and make what was once terse JavaScript code expand into several lines of type checking. This library aimed to simplify the experience of reducing the amount of type guards needed to process a typed-JSON data structure by providing several convenience functions that help extract well-typed data from such JSON structures.

For example, look at the following typical untyped JSON processing in JavaScript:

// concise, but not at all null-safe or type-safe; often made to be at least null-safe using lodash fns
JSON.parse(response.body).results.forEach(item => db.save(item.id, item));

Then a safe version in bare TypeScript using type guards:

const json = JSON.parse(response.body);
// type of json -> `any`, but will not be undefined or JSON.parse would throw
if (json === null && typeof json !== 'object') throw new Error('Unexpected json data type');
let results = json.results;
// type of results -> `any`
if (!Array.isArray(results)) results = [];
// type of results -> `any[]`
results.forEach(item => {
  // type of item -> `any`
  const id = item.id;
  // type of id -> `any`
  if (typeof id !== 'string') throw new Error('Unexpected item id data type');
  // type of id -> `string`
  db.save(id, item);
});

While that's pretty safe, it's also a mess to read and write. That's why this library is here to help!

const json = ensureJsonMap(JSON.parse(response.body));
// type of json -> `JsonMap` or raises an error
const results = asJsonArray(json.results, []);
// type of results -> `JsonArray` or uses the default of `[]`
results.forEach(item => {
  // type of item -> `AnyJson`
  record = ensureJsonMap(record);
  db.save(ensureString(record.id), record);
});

Removing the comments, we can shorten the above somewhat to achieve something not much more complex than the original example, but with robust type and null checking implemented:

asJsonArray(ensureJsonMap(JSON.parse(response.body)).results, []).forEach(item => {
  const record = ensureJsonMap(item);
  db.save(ensureString(record.id), record);
});

The ensure* functions are used in this example since they will raise an error when the value being checked either does not exist or does not match the expected type. Additionally, and perhaps more importantly, the generic any and AnyJson types get progressively narrowed when using these functions to more specific types. Of course, you don't always want to raise an error when these conditions are not met, so alternative forms exist for each of the JSON data types that allow the types to be tested and narrowed -- see the is* and as* variants in the API documentation for testing and narrowing capabilities without additionally raising errors.

Beyond JSON

After a few iterations of working on the JSON support types and utilities, it became apparent that we needed other non-JSON types and functions that provide similar capabilities. Rather than create a new library for those, we instead grew the scope of this one to contain all of our commonly used types and narrowing functions.

Types

A small library of types is included to help write more concise TypeScript code. These types are in part designed to augment the standard types included with the TypeScript library. Please see the generated API documentation for the complete set of provided types. Here are a few of the most commonly used types:

  • Optional<T>: An alias for the union type T | undefined.
  • NonOptional<T>: Subtracts undefined from a type T, when T includes undefined as a union member.
  • Nullable<T>: An alias for the union type Optional<T | null>, or T | null | undefined. NonNullable is a TypeScript built-in that subtracts both null and undefined from a type T with either as a union member.
  • Dictionary<T=unknown>: An alias for a string-indexed object of the form { [key: string]: Optional<T> }.
  • KeyOf<T>: An alias for the commonly needed yet verbose Extract<keyof T, string>.
  • AnyJson: A union type of all valid JSON values, equal to JsonPrimitive | JsonCollection.
  • JsonPrimitive: A union of all valid JSON primitive values, qual to null | string | number| boolean.
  • JsonMap: A dictionary of any valid JSON value, defined as Dictionary<AnyJson>.
  • JsonArray: An array of any valid JSON value, defined as Array<AnyJson>.
  • JsonCollection: A union of all JSON collection types, equal to JsonMap | JsonArray.

Narrowing functions

This library provides several categories of functions to help with safely narrowing variables of broadly typed variables, like unknown or object, to more specific types.

is*

The is* suite of functions accept a variable of a broad type such as unknown or object and returns a boolean type-predicate useful for narrowing the type in conditional scopes.

// type of value -> string | boolean
if (isString(value)) {
  // type of value -> string
}
// type of value -> boolean

as*

The as* suite of functions accept a variable of a broad type such as unknown or object and optionally returns a narrowed type after validating it with a runtime test. If the test is negative or if the value was not defined (i.e. undefined or null), undefined is returned instead.

// some function that takes a string or undefined
function upperFirst(s: Optional<string>): Optional<string> {
  return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
}
// type of value -> unknown
const name = upperFirst(asString(value));
// type of name -> Optional<string>

ensure*

The ensure* suite of functions narrow values' types to a definite value of the designated type, or raises an error if the value is undefined or of an incompatible type.

// type of value -> unknown
try {
  const s = ensureString(value);
  // type of s -> string
} catch (err) {
  // s was undefined, null, or not of type string
}

has*

The has* suite of functions both tests for the existence and type-compatibility of a given value and, if the runtime value check succeeds, narrows the type to a view of the original value's type intersected with the tested property (e.g. T & { [_ in K]: V } where K is the test property key and V is the test property value type).

// type of value -> unknown
if (hasString(value, 'name')) {
  // type of value -> { name: string }
  // value can be further narrowed with additional checks
  if (hasArray(value, 'results')) {
    // type of value -> { name: string } & { results: Array<unknown> }
  } else if (hasInstance(value, 'error', Error)) {
    // type of value -> { name: string } & { error: Error }
  }
}

get*

The get* suite of functions search an unknown target value for a given path. Search paths follow the same syntax as lodash's get, set, at, etc. These functions are more strictly typed, however, increasingly the likelihood that well-typed code stays well-typed as a function's control flow advances.

// imagine response json retrieved from a remote query
const response = {
  start: 0,
  length: 2,
  results: [{ name: 'first' }, { name: 'second' }]
};
const nameOfFirst = getString(response, 'results[0].name');
// type of nameOfFirst = string

coerce*

The coerce suite of functions accept values of general types and narrow their types to JSON-specific values. They are named with the coerce prefix to indicate that they do not perform an exhaustive runtime check of the entire data structure -- only shallow type checks are performed. As a result, only use these functions when you are confident that the broadly typed subject being coerced was derived from a JSON-compatible value. If you are unsure of an object's origins or contents but want to avoid runtime errors handling elements, see the to* set of functions.

const response = coerceJsonMap(JSON.parse(await http.get('http://example.com/data.json').body));
// type of response -> JsonMap

to*

The to* suite of functions is a fully type-safe version of the coerce* functions for JSON narrowing, but at the expense of some runtime performance. Under the hood, the to* functions perform a JSON-clone of their subject arguments, ensuring that the entire data structure is JSON compatible before returning the narrowed type.

const obj = {
  name: 'example',
  parse: function(s) {
    return s.split(':');
  }
};
const json = toJsonMap(obj);
// type of json -> JsonMap
// json = { name: 'example' }
// notice that the parse function has been omitted to ensure JSON-compatibility!

object utilities

This suite of functions are used to iterate the keys, entries, and values of objects with some typing conveniences applied that are not present in their built-in counterparts (i.e. Object.keys, Object.entries, and Object.values), but come with some caveats noted in their documentation. Typical uses include iterating over the properties of an object with more useful keyof typings applied during the iterator bodies, and/or filtering out undefined or null values before invoking the iterator functions.

const pets: Dictionary<string> = {
  fido: 'dog',
  bill: 'cat',
  fred: undefined
};
// note that the array is typed as [string, string] rather than [string, string | undefined]
function logPet([name, type]: [string, string]) {
  console.log('%s is a %s', name, type);
}
definiteEntriesOf(pets).forEach(logPet);
// fido is a dog
// bill is a cat

References

Another Salesforce TypeScript library, @salesforce/kit, builds on this library to add additional utilities. It includes additional JSON support, a lightweight replacement for some lodash functions, and growing support for patterns used in other Salesforce CLI libraries and applications.

Index

Type aliases

AnyConstructor

AnyConstructor: object

A constructor for any type T. T defaults to object when not explicitly supplied.

Type declaration

AnyFunction

AnyFunction: function

Any function returning type T. T defaults to unknown when not explicitly supplied.

Type declaration

    • (...args: any[]): T
    • Parameters

      • Rest ...args: any[]

      Returns T

AnyJson

Any valid JSON value.

JsonCollection

JsonCollection: JsonMap | JsonArray

Any valid JSON collection value.

JsonPrimitive

JsonPrimitive: null | boolean | number | string

Any valid JSON primitive value.

KeyOf

KeyOf: Extract<keyof T, string>

An alias for the commonly needed Extract<keyof T, string>.

KeyValue

KeyValue: [string, T]

An alias for a tuple of type [string, T]' for a given generic typeT.Tdefaults tounknown` if not otherwise defined.

Literals

Literals: Extract<{ [K in keyof T]: string extends K ? never : number extends K ? never : K; } extends { [_ in keyof T]: infer U; } ? U : never, string>

Extracts literally defined property names from a type T as a union of key name strings, minus any index signatures.

LiteralsRecord

LiteralsRecord: Record<Literals<T>, U>

Creates a new Record type from the literal properties of a type T, assigning their values the to the type U.

This can be useful for creating interfaces from the keys of an enum so that the keys are available at runtime for meta-programming purposes, while both tying the properties of the generated type to the enum keys and remaining as DRY as possible.

enum QUERY_KEY { id, name, created, updated }
// type of QUERY_KEY -> {
//     [x: number]: number;
//     readonly id: number;
//     readonly name: number;
//     readonly created: number;
//     readonly updated: number;
// }
interface QueryRecord extends LiteralsRecord<typeof QUERY_KEY, string> { }
// type of QueryRecord -> {
//     readonly id: string;
//     readonly name: string;
//     readonly created: string;
//     readonly updated: string;
// }
// And for an interface with writable properties, use the following:
interface QueryRecord extends ReadWrite<LiteralsRecord<typeof QUERY_KEY, string>> { }
// type of QueryRecord -> {
//     id: string;
//     name: string;
//     created: string;
//     updated: string;
// }

Many

Many: T | T[]

A union type for either the parameterized type T or an array of T.

NonOptional

NonOptional: NonOptional<T>

Subtracts undefined from any union type T. This is the opposite of Optional.

Nullable

Nullable: Optional<T | null>

A union type for either the parameterized type T, null, or undefined -- the opposite of the NonNullable builtin conditional type.

Omit

Omit: Pick<T, Exclude<keyof T, K>>

Creates a new type that omits keys in union type K of a target type T.

Optional

Optional: T | undefined

A union type for either the parameterized type T or undefined -- the opposite of NonOptional.

Overwrite

Overwrite: object & T2

Returns a new type consisting of all properties declared for an input type T2 overlaid on the properties of type T1. Any definitions in T2 replace those previously defined in T1. This can be useful for redefining the types of properties on T1 with values from an inline type T2, perhaps to change their type or to make them optional.

type NameAndStringValue = { name: string, value: string }
type NameAndOptionalNumericValue = Overwrite<NameAndValue, { value?: number }>
// type of NameAndOptionalNumericValue -> { name: string } & { value?: number | undefined }

ReadWrite

ReadWrite: object

Converts readonly properties of a type T to writable properties. This is the opposite of the Readonly<T> builtin mapped type.

Type declaration

RequiredNonNullable

RequiredNonNullable: RequiredNonNullable<T>

Converts a type T that may have optional, nullable properties into a new type with only required properties, while also subtracting null from all possible property values.

type Foo = { bar?: string | undefined | null };
type RequiredNonNullableFoo = RequiredNonNullable<Foo>;
// RequiredNonNullableFoo -> { bar: string };

RequiredNonOptional

RequiredNonOptional: RequiredNonOptional<T>

Converts a type T that may have optional properties into a type T with only required properties (e.g. undefined values are not allowed). Explicit nulls in value unions will still be possible. This is similar to the Required builtin mapped type, but also subtracts undefined from value union types as well as the optional property declaration.

type Foo = { bar?: string | undefined | null };
type RequiredNonOptionalFoo = RequiredNonOptional<Foo>;
// RequiredNonOptionalFoo -> { bar: string | null };

View

View: object

A view over an object with constrainable properties.

Type declaration

Functions

asArray

  • Narrows an unknown value to an Array if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<AnyArray>

  • Narrows an unknown value to an object if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: AnyArray

      The default to return if value was undefined or of the incorrect type.

    Returns AnyArray

asBoolean

  • asBoolean(value: unknown): Optional<boolean>
  • asBoolean(value: unknown, defaultValue: boolean): boolean
  • Narrows an unknown value to a boolean if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<boolean>

  • Narrows an unknown value to a boolean if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: boolean

      The default to return if value was undefined or of the incorrect type.

    Returns boolean

asFunction

  • Narrows an unknown value to an AnyFunction if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<AnyFunction>

  • Narrows an unknown value to an object if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: AnyFunction

      The default to return if value was undefined or of the incorrect type.

    Returns AnyFunction

asInstance

  • asInstance<C>(value: unknown, ctor: C): Optional<InstanceType<C>>
  • asInstance<C>(value: unknown, ctor: C, defaultValue: InstanceType<C>): InstanceType<C>
  • Narrows an unknown value to an instance of constructor type T if it is type-compatible, or returns undefined otherwise.

    Type parameters

    Parameters

    • value: unknown

      The value to test.

    • ctor: C

    Returns Optional<InstanceType<C>>

  • Narrows an unknown value to an object if it is type-compatible, or returns the provided default otherwise.

    Type parameters

    Parameters

    • value: unknown

      The value to test.

    • ctor: C
    • defaultValue: InstanceType<C>

      The default to return if value was undefined or of the incorrect type.

    Returns InstanceType<C>

asJsonArray

  • Narrows an AnyJson value to a JsonArray if it is type-compatible, or returns undefined otherwise.

    Parameters

    Returns Optional<JsonArray>

  • Narrows an AnyJson value to a JsonArray if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: Optional<AnyJson>

      The value to test.

    • defaultValue: JsonArray

      The default to return if the value was undefined or of the incorrect type.

    Returns JsonArray

asJsonMap

  • Narrows an AnyJson value to a JsonMap if it is type-compatible, or returns undefined otherwise.

    Parameters

    Returns Optional<JsonMap>

  • Narrows an AnyJson value to a JsonMap if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: Optional<AnyJson>

      The value to test.

    • defaultValue: JsonMap

      The default to return if value was undefined or of the incorrect type.

    Returns JsonMap

asNumber

  • asNumber(value: unknown): Optional<number>
  • asNumber(value: unknown, defaultValue: number): number
  • Narrows an unknown value to a number if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<number>

  • Narrows an unknown value to a number if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: number

      The default to return if value was undefined or of the incorrect type.

    Returns number

asObject

  • asObject(value: unknown): Optional<any>
  • asObject(value: unknown, defaultValue: object): object
  • Narrows an unknown value to an object if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<any>

  • Narrows an unknown value to an object if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: object

      The default to return if value was undefined or of the incorrect type.

    Returns object

asPlainObject

  • asPlainObject(value: unknown): Optional<any>
  • asPlainObject(value: unknown, defaultValue: object): object
  • Narrows an unknown value to a plain object if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<any>

  • Narrows an unknown value to an object if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: object

      The default to return if value was undefined or of the incorrect type.

    Returns object

asString

  • asString(value: unknown): Optional<string>
  • asString(value: unknown, defaultValue: string): string
  • Narrows an unknown value to a string if it is type-compatible, or returns undefined otherwise.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<string>

  • Narrows an unknown value to a string if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: string

      The default to return if value was undefined or of the incorrect type.

    Returns string

coerceAnyJson

  • Narrows an unknown value to an AnyJson if it is type-compatible*, or returns undefined otherwise.

    * This is not a 100% safe operation -- it will not deeply validate plain object or array structures to ensure that they contain only AnyJson values. When type-narrowing potential objects or arrays with this function, it's the responsibility of the caller to understand the risks of making such a shallow type assertion over the value data.

    Parameters

    • value: unknown

      The value to test.

    Returns Optional<AnyJson>

  • Narrows an unknown value to an AnyJson if it is type-compatible, or returns the provided default otherwise.

    Parameters

    • value: unknown

      The value to test.

    • defaultValue: AnyJson

      The default to return if value was undefined or of the incorrect type.

    Returns AnyJson

coerceJsonArray

  • Narrows an array of type T to a JsonArray using a shallow type-compatibility check. Use this when the source of the array is known to be JSON-compatible and you want simple type coercion to a JsonArray. Use toJsonArray instead when the value array cannot be guaranteed to be JSON-compatible and you want an assurance of runtime type safety. This is a shortcut for writing asJsonArray(coerceAnyJson(value)).

    Type parameters

    • T

    Parameters

    • value: Nullable<T[]>

      The array to coerce.

    Returns Optional<JsonArray>

  • Narrows an array of type T to a JsonArray using a shallow type-compatibility check. Use this when the source of the array is known to be JSON-compatible and you want simple type coercion to a JsonArray. Use toJsonArray instead when the value array cannot be guaranteed to be JSON-compatible and you want an assurance of runtime type safety. This is a shortcut for writing asJsonArray(coerceAnyJson(value)) || defaultValue.

    Type parameters

    • T

    Parameters

    • value: Nullable<T[]>

      The array to coerce.

    • defaultValue: JsonArray

      The default to return if value was not defined.

    Returns JsonArray

coerceJsonMap

  • Narrows an object of type T to a JsonMap using a shallow type-compatibility check. Use this when the source of the object is known to be JSON-compatible and you want simple type coercion to a JsonMap. Use toJsonMap instead when the value object cannot be guaranteed to be JSON-compatible and you want an assurance of runtime type safety. This is a shortcut for writing asJsonMap(coerceAnyJson(value)).

    Type parameters

    • T: any

    Parameters

    • value: Nullable<T>

      The object to coerce.

    Returns Optional<JsonMap>

  • Narrows an object of type T to a JsonMap using a shallow type-compatibility check. Use this when the source of the object is known to be JSON-compatible and you want simple type coercion to a JsonMap. Use toJsonMap instead when the value object cannot be guaranteed to be JSON-compatible and you want an assurance of runtime type safety. This is a shortcut for writing asJsonMap(coerceAnyJson(value)) || defaultValue.

    Type parameters

    • T: any

    Parameters

    • value: Nullable<T>

      The object to coerce.

    • defaultValue: JsonMap

      The default to return if value was not defined.

    Returns JsonMap

definiteEntriesOf

  • definiteEntriesOf<T, K, V>(obj: Nullable<T>): Array<[K, V]>
  • Returns an array of all entry tuples of type [K, NonNullable<T[K]>] in an object T whose values are neither null nor undefined. This can be convenient for enumerating the entries of unknown objects with optional properties (including Dictionarys) without worrying about performing checks against possibly undefined or null values.

    See also caveats outlined in entriesOf.

    Type parameters

    • T: any

    • K: KeyOf<T>

    • V: NonNullable<T[K]>

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns Array<[K, V]>

definiteKeysOf

  • Returns an array of all string keys in an object of type T whose values are neither null nor undefined. This can be convenient for enumerating the keys of definitely assigned properties in an object or Dictionary.

    See also caveats outlined in keysOf.

    Type parameters

    • T: any

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns Array<KeyOf<T>>

definiteValuesOf

  • definiteValuesOf<T>(obj: Nullable<T>): Array<NonNullable<T[Extract<keyof T, string>]>>
  • Returns an array of all values of type T in an object T for values that are neither null nor undefined. This can be convenient for enumerating the values of unknown objects with optional properties (including Dictionarys) without worrying about performing checks against possibly undefined or null values.

    Type parameters

    • T: any

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns Array<NonNullable<T[Extract<keyof T, string>]>>

ensure

  • ensure<T>(value: Nullable<T>, message?: undefined | string): T
  • Narrows a type Nullable<T> to a T or raises an error.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Type parameters

    • T

    Parameters

    • value: Nullable<T>

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is undefined or null.

    Returns T

ensureAnyJson

  • ensureAnyJson(value: unknown, message?: undefined | string): AnyJson
  • Narrows an unknown value to an AnyJson if it is type-compatible, or returns undefined otherwise.

    See also caveats noted in isAnyJson.

    throws

    UnexpectedValueTypeError If the value was not a JSON value type.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns AnyJson

ensureArray

  • ensureArray(value: unknown, message?: undefined | string): AnyArray
  • Narrows an unknown value to an Array if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns AnyArray

ensureBoolean

  • ensureBoolean(value: unknown, message?: undefined | string): boolean
  • Narrows an unknown value to a boolean if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns boolean

ensureFunction

  • ensureFunction(value: unknown, message?: undefined | string): AnyFunction
  • Narrows an unknown value to an AnyFunction if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns AnyFunction

ensureInstance

  • ensureInstance<C>(value: unknown, ctor: C, message?: undefined | string): InstanceType<C>
  • Narrows an unknown value to instance of constructor type T if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Type parameters

    Parameters

    • value: unknown

      The value to test.

    • ctor: C
    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns InstanceType<C>

ensureJsonArray

  • Narrows an AnyJson value to a JsonArray if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: Optional<AnyJson>

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns JsonArray

ensureJsonMap

  • Narrows an AnyJson value to a JsonMap if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: Optional<AnyJson>

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns JsonMap

ensureNumber

  • ensureNumber(value: unknown, message?: undefined | string): number
  • Narrows an unknown value to a number if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns number

ensureObject

  • ensureObject(value: unknown, message?: undefined | string): object
  • Narrows an unknown value to an object if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns object

ensurePlainObject

  • ensurePlainObject(value: unknown, message?: undefined | string): object
  • Narrows an unknown value to an object if it is type-compatible and tests positively with isPlainObject, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns object

ensureString

  • ensureString(value: unknown, message?: undefined | string): string
  • Narrows an unknown value to a string if it is type-compatible, or raises an error otherwise.

    throws

    UnexpectedValueTypeError If the value was undefined.

    Parameters

    • value: unknown

      The value to test.

    • Optional message: undefined | string

      The error message to use if value is not type-compatible.

    Returns string

entriesOf

  • entriesOf<T, K>(obj: Nullable<T>): Array<[K, T[K]]>
  • Returns the entries of an object of type T. This is like Object.entries except the return type captures the known keys and value types of T.

    Note that it is the responsibility of the caller to use this wisely -- there are cases where the runtime set of entries returned may be broader than the type checked set at compile time, so there's potential for this to be abused in ways that are not inherently type safe. For example, given base class Animal, subclass Fish, and const animal: Animal = new Fish(); then entriesOf(animal) will not type-check the entire set of keys of the object animal since it is actually an instance of type Fish, which has an extended property set.

    In general, it should be both convenient and type-safe to use this when enumerating the entries of simple data objects with known properties.

    interface Point { x: number; y: number; }
    const point: Point = { x: 1, y: 2 };
    // type of entries -> ['x' | 'y', number][]
    const entries = entriesOf(point);
    for (const entry of entries) {
      console.log(entry[0], entry[1]);
    }
    // x 1
    // y 2

    Type parameters

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns Array<[K, T[K]]>

get

  • get(from: unknown, path: string, defaultValue?: unknown): unknown
  • Given a deep-search query path, returns an object property or array value of an object or array.

    const obj = { foo: { bar: ['baz'] } };
    const value = get(obj, 'foo.bar[0]');
    // type of value -> unknown; value === 'baz'
    
    const value = get(obj, 'foo.bar.nothing', 'default');
    // type of value -> unknown; value === 'default'
    
    const value = get(obj, 'foo["bar"][0]');
    // type of value -> unknown; value === 'baz'
    
    const arr = [obj];
    const value = get(arr, '[0].foo.bar[0]');
    // type of value -> unknown; value === 'baz'

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • Optional defaultValue: unknown

      The default to return if the query result was not defined.

    Returns unknown

getAnyJson

  • Given a deep-search query path, returns an object property or array value of a JsonCollection as an AnyJson, or undefined if a value was not found or was not type-compatible.

    See coerceAnyJson for caveats regarding shallow type detection of AnyJson values from untyped sources.

    const obj = { foo: { bar: [{ a: 'b' }] } };
    const value = getAnyJson(obj, 'foo.bar[0]');
    // type of value -> AnyJson; value -> { a: 'b' }

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    Returns Optional<AnyJson>

  • Given a deep-search query path, returns an object property or array value of a JsonCollection as an AnyJson, or the given default if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [{ a: 'b' }] } };
    const value = getAnyJson(obj, 'foo.bar[1]', { c: 'd' });
    // type of value -> AnyJson; value -> { c: 'd' }

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    • defaultValue: AnyJson

      The default to return if the query result was not defined.

    Returns AnyJson

getArray

  • Given a deep-search query path, returns an object property or array value of an object or array as an AnyArray, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1, 2, 3] } };
    const value = getArray(obj, 'foo.bar');
    // type of value -> AnyArray; value -> [1, 2, 3]

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<AnyArray>

  • Given a deep-search query path, returns an object property or array value of an object or array as an AnyArray, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1, 2, 3] } };
    const value = getArray(obj, 'foo.baz', [4, 5, 6]);
    // type of value -> AnyArray; value -> [4, 5, 6]

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: AnyArray

      The default to return if the query result was not defined.

    Returns AnyArray

getBoolean

  • getBoolean(from: unknown, path: string): Nullable<boolean>
  • getBoolean(from: unknown, path: string, defaultValue: boolean): boolean
  • Given a deep-search query path, returns an object property or array value of an object or array as a boolean, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [true] } };
    const value = getBoolean(obj, 'foo.bar[0]');
    // type of value -> boolean; value -> true

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<boolean>

  • Given a deep-search query path, returns an object property or array value of an object or array as a boolean, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [true] } };
    const value = getBoolean(obj, 'foo.bar[1]', false);
    // type of value -> boolean; value -> false

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: boolean

      The default to return if the query result was not defined.

    Returns boolean

getFunction

  • Given a deep-search query path, returns an object property or array value of an object or array as an AnyFunction, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [(arg: string) => `Hi, ${arg}`] } };
    const value = getFunction(obj, 'foo.bar[0]');
    // type of value -> AnyArray; value -> (arg: string) => `Hi, ${arg}`

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<AnyFunction>

  • Given a deep-search query path, returns an object property or array value of an object or array as an AnyFunction, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [(arg: string) => `Hi, ${arg}`] } };
    const value = getFunction(obj, 'foo.bar[1]', (arg: string) => `Bye, ${arg}`);
    // type of value -> AnyArray; value -> (arg: string) => `Bye, ${arg}`)

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: AnyFunction

      The default to return if the query result was not defined.

    Returns AnyFunction

getInstance

  • getInstance<C>(from: unknown, path: string, ctor: C): Nullable<InstanceType<C>>
  • getInstance<C>(from: unknown, path: string, ctor: C, defaultValue: InstanceType<C>): InstanceType<C>
  • Given a deep-search query path, returns an object property or array value of an object or array as an instance of class type C, or undefined if a value was not found or was not type-compatible.

    class Example { ... }
    const obj = { foo: { bar: [new Example()] } };
    const value = getInstance(obj, 'foo.bar[0]', Example);
    // type of value -> Example

    Type parameters

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • ctor: C

    Returns Nullable<InstanceType<C>>

  • Given a deep-search query path, returns an object property or array value of an object or array as an instance of class type C, or undefined if a value was not found or was not type-compatible.

    class Example { ... }
    const obj = { foo: { bar: [new Example()] } };
    const value = getInstance(obj, 'foo.bar[0]', Example);
    // type of value -> Example; value -> new Example()

    Type parameters

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • ctor: C
    • defaultValue: InstanceType<C>

      The default to return if the query result was not defined.

    Returns InstanceType<C>

getJsonArray

  • Given a deep-search query path, returns an object property or array value from an AnyJson as a JsonArray, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1, 2, 3] } };
    const value = getJsonArray(obj, 'foo.bar');
    // type of value -> JsonArray; value -> [1, 2, 3]

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    Returns Nullable<JsonArray>

  • Given a deep-search query path, returns an object property or array value from an AnyJson as a JsonArray, or the given default if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1, 2, 3] } };
    const value = getJsonArray(obj, 'foo.baz', [4, 5, 6]);
    // type of value -> JsonArray; value -> [4, 5, 6]

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    • defaultValue: JsonArray

      The default to return if the query result was not defined.

    Returns JsonArray

getJsonMap

  • Given a deep-search query path, returns an object property or array value from an AnyJson as a JsonMap, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [{ a: 'b' }] } };
    const value = getJsonMap(obj, 'foo.bar[0]');
    // type of value -> JsonMap; value -> { a: 'b' }

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    Returns Nullable<JsonMap>

  • Given a deep-search query path, returns an object property or array value from an AnyJson as a JsonMap, or the given default if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [{ a: 'b' }] } };
    const value = getJsonMap(obj, 'foo.bar[1]', { c: 'd' });
    // type of value -> JsonMap; value -> { c: 'd' }

    Parameters

    • from: Optional<AnyJson>

      The JSON value to query.

    • path: string

      The query path.

    • defaultValue: JsonMap

      The default to return if the query result was not defined.

    Returns JsonMap

getNumber

  • getNumber(from: unknown, path: string): Nullable<number>
  • getNumber(from: unknown, path: string, defaultValue: number): number
  • Given a deep-search query path, returns an object property or array value of an object or array as a number, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1] } };
    const value = getNumber(obj, 'foo.bar[0]');
    // type of value -> number; value -> 1

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<number>

  • Given a deep-search query path, returns an object property or array value of an object or array as a number, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [1] } };
    const value = getNumber(obj, 'foo.bar[1]', 2);
    // type of value -> number; value -> 2

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: number

      The default to return if the query result was not defined.

    Returns number

getObject

  • getObject(from: unknown, path: string): Nullable<any>
  • getObject(from: unknown, path: string, defaultValue: object): object
  • Given a deep-search query path, returns an object property or array value of an object or array as an object, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [{ name: 'baz' }] } };
    const value = getObject(obj, 'foo.bar[0]');
    // type of value -> object; value -> { name: 'baz' }

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<any>

  • Given a deep-search query path, returns an object property or array value of an object or array as an object, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: [{ name: 'baz' }] } };
    const value = getObject(obj, 'foo.bar[1]', { name: 'buzz' });
    // type of value -> object; value -> { name: 'buzz' }

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: object

      The default to return if the query result was not defined.

    Returns object

getPlainObject

  • getPlainObject(from: unknown, path: string): Nullable<any>
  • getPlainObject(from: unknown, path: string, defaultValue: object): object
  • Given a deep-search query path, returns an object property or array value of an object or array as an object, or undefined if a value was not found or was not type-compatible. This differs from getObject by way of testing for the property value type compatibility using isPlainObject instead of isObject.

    const obj = { foo: { bar: [{ name: 'baz' }] } };
    const value = getPlainObject(obj, 'foo.bar[0]');
    // type of value -> object; value -> { name: 'baz' }

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<any>

  • Given a deep-search query path, returns an object property or array value of an object or array as an object, or undefined if a value was not found or was not type-compatible. This differs from getObject by way of testing for the property value type compatibility using isPlainObject instead of isObject.

    const obj = { foo: { bar: [{ name: 'baz' }] } };
    const value = getPlainObject(obj, 'foo.bar[1]', { name: 'buzz' });
    // type of value -> object; value -> { name: 'buzz' }

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: object

      The default to return if the query result was not defined.

    Returns object

getString

  • getString(from: unknown, path: string): Nullable<string>
  • getString(from: unknown, path: string, defaultValue: string): string
  • Given a deep-search query path, returns an object property or array value of an object or array as a string, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: ['baz'] } };
    const value = getString(obj, 'foo.bar[0]');
    // type of value -> string; value -> 'baz'

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    Returns Nullable<string>

  • Given a deep-search query path, returns an object property or array value of an object or array as a string, or undefined if a value was not found or was not type-compatible.

    const obj = { foo: { bar: ['baz'] } };
    const value = getString(obj, 'foo.bar[1]', 'default');
    // type of value -> string; value -> 'default'

    Parameters

    • from: unknown

      Any value to query.

    • path: string

      The query path.

    • defaultValue: string

      The default to return if the query result was not defined.

    Returns string

has

  • has<T, K>(value: T, keys: Many<K>): boolean
  • Tests whether a value of type T contains one or more property keys. If so, the type of the tested value is narrowed to reflect the existence of those keys for convenient access in the same scope. Returns false if the property key does not exist on the target type, which must be an object. Returns true if the property key exists, even if the associated value is undefined or null.

    // type of obj -> unknown
    if (has(obj, 'name')) {
      // type of obj -> { name: unknown }
      if (has(obj, 'data')) {
        // type of obj -> { name: unknown } & { data: unknown }
      } else if (has(obj, ['error', 'status'])) {
        // type of obj -> { name: unknown } & { error: unknown, status: unknown }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • keys: Many<K>

      One or more string keys to check for existence.

    Returns boolean

hasAnyJson

  • hasAnyJson<T, K>(value: Optional<T>, key: K): boolean
  • Tests whether a value of type T contains a property key of type AnyJson, using a shallow test for AnyJson compatibility (see isAnyJson for more information). If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type AnyJson.

    // type of obj -> unknown
    if (hasAnyJson(obj, 'body')) {
      // type of obj -> { body: AnyJson }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K

    Returns boolean

hasArray

  • hasArray<T, K>(value: Optional<T>, key: K): boolean
  • Tests whether a value of type T contains a property key of type AnyArray. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type AnyArray.

    // type of obj -> unknown
    if (hasNumber(obj, 'offset')) {
      // type of obj -> { offset: number }
      if (hasNumber(obj, 'page') && hasArray(obj, 'items')) {
        // type of obj -> { offset: number } & { page: number } & { items: AnyArray }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K

    Returns boolean

hasBoolean

  • hasBoolean<T, K>(value: T, key: K): boolean
  • Tests whether a value of type T contains a property key of type boolean. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type boolean.

    // type of obj -> unknown
    if (hasBoolean(obj, 'enabled')) {
      // type of obj -> { enabled: boolean }
      if (hasBoolean(obj, 'hidden')) {
        // type of obj -> { enabled: boolean } & { hidden: boolean }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • key: K

    Returns boolean

hasFunction

  • hasFunction<T, K>(value: Optional<T>, key: K): boolean
  • Tests whether a value of type T contains a property key of type AnyFunction. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type AnyFunction.

    // type of obj -> unknown
    if (hasFunction(obj, 'callback')) {
      // type of obj -> { callback: AnyFunction }
      obj.callback(response);
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K

    Returns boolean

hasInstance

  • hasInstance<T, K, C>(value: Optional<T>, key: K, ctor: C): boolean
  • Tests whether a value of type T contains a property key whose type tests positively when tested with isInstance when compared with the given constructor type C. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not an instance of C.

    class ServerResponse { ... }
    // type of obj -> unknown
    if (hasNumber(obj, 'status')) {
      // type of obj -> { status: number }
      if (hasInstance(obj, 'data', ServerResponse)) {
        // type of obj -> { status: number } & { data: ServerResponse }
      } else if (hasString('error')) {
        // type of obj -> { status: number } & { error: string }
      }
    }

    Type parameters

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K
    • ctor: C

    Returns boolean

hasJsonArray

  • hasJsonArray<T, K>(value: Optional<T>, key: K): boolean
  • Tests whether a value of type T extends AnyJson contains a property key of type JsonArray. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type JsonArray.

    // type of obj -> unknown
    if (hasJsonArray(obj, 'body')) {
      // type of obj -> { body: JsonArray }
    }

    Type parameters

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K

    Returns boolean

hasJsonMap

  • hasJsonMap<T, K>(value: Optional<T>, key: K): boolean
  • Tests whether a value of type T extends AnyJson contains a property key of type JsonMap. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type JsonMap.

    // type of obj -> unknown
    if (hasJsonMap(obj, 'body')) {
      // type of obj -> { body: JsonMap }
    }

    Type parameters

    Parameters

    • value: Optional<T>

      The value to test.

    • key: K

    Returns boolean

hasNumber

  • hasNumber<T, K>(value: T, key: K): boolean
  • Tests whether a value of type T contains a property key of type number. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type number.

    // type of obj -> unknown
    if (hasNumber(obj, 'offset')) {
      // type of obj -> { offset: number }
      if (hasNumber(obj, 'page') && hasArray(obj, 'items')) {
        // type of obj -> { offset: number } & { page: number } & { items: Array<unknown> }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • key: K

    Returns boolean

hasObject

  • hasObject<T, K>(value: T, key: K): boolean
  • Tests whether a value of type T contains a property key of type object. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type object.

    // type of obj -> unknown
    if (hasNumber(obj, 'status')) {
      // type of obj -> { status: number }
      if (hasObject(obj, 'data')) {
        // type of obj -> { status: number } & { data: object }
      } else if (hasString('error')) {
        // type of obj -> { status: number } & { error: string }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • key: K

    Returns boolean

hasPlainObject

  • hasPlainObject<T, K>(value: T, key: K): boolean
  • Tests whether a value of type T contains a property key whose type tests positively when tested with isPlainObject. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type object.

    // type of obj -> unknown
    if (hasNumber(obj, 'status')) {
      // type of obj -> { status: number }
      if (hasPlainObject(obj, 'data')) {
        // type of obj -> { status: number } & { data: object }
      } else if (hasString('error')) {
        // type of obj -> { status: number } & { error: string }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • key: K

    Returns boolean

hasString

  • hasString<T, K>(value: T, key: K): boolean
  • Tests whether a value of type T contains a property key of type string. If so, the type of the tested value is narrowed to reflect the existence of that key for convenient access in the same scope. Returns false if the property key does not exist on the object or the value stored by that key is not of type string.

    // type of obj -> unknown
    if (hasString(obj, 'name')) {
      // type of obj -> { name: string }
      if (hasString(obj, 'message')) {
        // type of obj -> { name: string } & { message: string }
      }
    }

    Type parameters

    • T: unknown

    • K: string

    Parameters

    • value: T

      The value to test.

    • key: K

    Returns boolean

isAnyJson

  • isAnyJson(value: unknown): boolean
  • Tests whether unknown value is a valid JSON type. Note that objects and arrays are only checked using a shallow test. To be sure that a given value is JSON-compatible at runtime, see toAnyJson.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isArray

  • isArray(value: unknown): boolean
  • Tests whether an unknown value is an Array.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isArrayLike

  • isArrayLike(value: unknown): boolean

isBoolean

  • isBoolean(value: unknown): boolean
  • Tests whether an unknown value is a boolean.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isClassAssignableTo

  • isClassAssignableTo<C>(value: unknown, cls: C): boolean
  • Tests whether an unknown value is a class constructor that is either equal to or extends another class constructor.

    Type parameters

    Parameters

    • value: unknown

      The value to test.

    • cls: C

      The class to test against.

    Returns boolean

isFunction

  • isFunction(value: unknown): boolean
  • Tests whether an unknown value is a function.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isInstance

  • isInstance<C>(value: unknown, ctor: C): boolean
  • Tests whether an unknown value is a function.

    Type parameters

    Parameters

    • value: unknown

      The value to test.

    • ctor: C

    Returns boolean

isJsonArray

isJsonMap

isKeyOf

  • isKeyOf<T, K>(obj: T, key: string): boolean
  • Tests whether or not a key string is a key of the given object type T.

    Type parameters

    Parameters

    • obj: T

      The target object to check the key in.

    • key: string

      The string to test as a key of the target object.

    Returns boolean

isNumber

  • isNumber(value: unknown): boolean
  • Tests whether an unknown value is a number.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isObject

  • isObject(value: unknown): boolean
  • Tests whether an unknown value is an Object subtype (e.g., arrays, functions, objects, regexes, new Number(0), new String(''), and new Boolean(true)). Tests that wish to distinguish objects that were created from literals or that otherwise were not created via a non-Object constructor and do not have a prototype chain should instead use isPlainObject.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isPlainObject

  • isPlainObject(value: unknown): boolean
  • Tests whether or not an unknown value is a plain JavaScript object. That is, if it is an object created by the Object constructor or one with a null prototype.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

isString

  • isString(value: unknown): boolean
  • Tests whether an unknown value is a string.

    Parameters

    • value: unknown

      The value to test.

    Returns boolean

keysOf

  • Returns the keys of an object of type T. This is like Object.keys except the return type captures the known keys of T.

    Note that it is the responsibility of the caller to use this wisely -- there are cases where the runtime set of keys returned may be broader than the type checked set at compile time, so there's potential for this to be abused in ways that are not inherently type safe. For example, given base class Animal, subclass Fish, and const animal: Animal = new Fish(); then keysOf(animal) will not type-check the entire set of keys of the object animal since it is actually an instance of type Fish, which has an extended property set.

    In general, it should be both convenient and type-safe to use this when enumerating the keys of simple data objects with known properties.

    interface Point { x: number; y: number; }
    const point: Point = { x: 1, y: 2 };
    const keys = keysOf(point);
    // type of keys -> ('a' | 'b')[]
    for (const key of keys) {
      console.log(key, point[key]);
    }
    // x 1
    // y 2

    Type parameters

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns K[]

toAnyJson

  • Narrows an object of type T to an AnyJson following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceAnyJson(unknown) to type-narrow an arbitrary value to an AnyJson when the value's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Use coerceAnyJson(unknown) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the value values contain circular references.

    Type parameters

    • T

    Parameters

    • value: Nullable<T>

      The value to convert.

    Returns Optional<AnyJson>

  • Narrows an object of type T to an AnyJson following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceAnyJson(unknown) to type-narrow an arbitrary value to an AnyJson when the value's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Use coerceAnyJson(unknown) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the value values contain circular references.

    Type parameters

    • T

    Parameters

    • value: Nullable<T>

      The value to convert.

    • defaultValue: AnyJson

      The default to return if value was not defined.

    Returns AnyJson

toJsonArray

  • Narrows an array of type T to a JsonArray following a deep, brute-force conversion of the array's data to only consist of JSON-compatible values by performing a basic JSON clone on the array. This is preferable to using the weaker coerceJsonArray(array) to type-narrow an arbitrary array to a JsonArray when the array's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Non-JSON entries will be converted to nulls. Use coerceJsonArray(array) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the array values contain circular references.

    Type parameters

    • T

    Parameters

    • value: T[]

      The array to convert.

    Returns JsonArray

  • Narrows an array of type T to a JsonArray following a deep, brute-force conversion of the array's data to only consist of JSON-compatible values by performing a basic JSON clone on the array. This is preferable to using the weaker coerceJsonArray(array) to type-narrow an arbitrary array to a JsonArray when the array's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Non-JSON entries will be converted to nulls. Use coerceJsonArray(array) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the array values contain circular references.

    Type parameters

    • T

    Parameters

    • value: Optional<T[]>

      The array to convert.

    Returns Optional<JsonArray>

  • Narrows an object of type T to a JsonMap following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceJsonMap(object) to type-narrow an arbitrary array to a JsonMap when the object's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Non-JSON entries will be converted to nulls. Use coerceJsonArray(array) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the array values contain circular references.

    Type parameters

    • T

    Parameters

    • value: Optional<T[]>

      The array to convert.

    • defaultValue: JsonArray

      The default to return if the value was undefined or of the incorrect type.

    Returns JsonArray

toJsonMap

  • Narrows an object of type T to a JsonMap following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceJsonMap(object) to type-narrow an arbitrary object to a JsonMap when the object's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Use coerceJsonMap(object) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the object values contain circular references.

    Type parameters

    • T: any

    Parameters

    • value: T

      The object to convert.

    Returns JsonMap

  • Narrows an object of type T to a JsonMap following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceJsonMap(object) to type-narrow an arbitrary object to a JsonMap when the object's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Use coerceJsonMap(object) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the object values contain circular references.

    Type parameters

    • T: any

    Parameters

    • value: Nullable<T>

      The object to convert.

    Returns Optional<JsonMap>

  • Narrows an object of type T to a JsonMap following a deep, brute-force conversion of the object's data to only consist of JSON-compatible values by performing a basic JSON clone on the object. This is preferable to using the weaker coerceJsonMap(object) to type-narrow an arbitrary object to a JsonMap when the object's source is unknown, but it comes with the increased overhead of performing the deep JSON clone to ensure runtime type safety. The use of JSON cloning guarantees type safety by omitting non-JSON-compatible elements from the resulting JSON data structure. Use coerceJsonMap(object) when the value object can be guaranteed to be JSON-compatible and only needs type coercion.

    throws

    JsonCloneError If the object values contain circular references.

    Type parameters

    • T: any

    Parameters

    • value: Nullable<T>

      The object to convert.

    • defaultValue: JsonMap

      The default to return if value was not defined.

    Returns JsonMap

valuesOf

  • valuesOf<T, K>(obj: Nullable<T>): Array<T[K]>
  • Returns the values of an object of type T. This is like Object.values except the return type captures the possible value types of T.

    Note that it is the responsibility of the caller to use this wisely -- there are cases where the runtime set of values returned may be broader than the type checked set at compile time, so there's potential for this to be abused in ways that are not inherently type safe. For example, given base class Animal, subclass Fish, and const animal: Animal = new Fish(); then valuesOf(animal) will not type-check the entire set of values of the object animal since it is actually an instance of type Fish, which has an extended property set.

    In general, it should be both convenient and type-safe to use this when enumerating the values of simple data objects with known properties.

    interface Point { x: number; y: number; }
    const point: Point = { x: 1, y: 2 };
    const values = valuesOf(point);
    // type of values -> number[]
    for (const value of values) {
      console.log(value);
    }
    // 1
    // 2

    Type parameters

    Parameters

    • obj: Nullable<T>

      The object of interest.

    Returns Array<T[K]>