Security News
Supply Chain Attack Detected in @solana/web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
ts-runtime-typecheck
Advanced tools
A collection of common types for TypeScript along with dynamic type cast methods.
Simple functions for validating complex data.
JavaScript is a very flexible language. Meaning it's easy to get tripped up by a value with an unexpected type. Even in TypeScript you occasionally have to deal with values which cannot be safely typed at compile time. This library provides a comprehensive selection of functions to simplify type checking code with clear and concise function calls. Ensuring strict type safety throughout your program, no matter the input.
Releases are available on the npm repository and our GitHub releases page. ESM and CJS formats are both included, as well as TypeScript type definition files. Both formats work without TypeScript if you prefer plain JS.
npm install ts-runtime-typecheck
Type Casts take an unknown
value as an argument, and return a typed value as the result. These functions take the form as{TYPE}
, for example asNumber
. If the input value does not match the required type the function will throw. This does not perform any coercion on the value, passing a string
of a number to asNumber
will cause it to throw.
import { asNumber } from 'ts-runtime-typecheck';
function square (input: unknown): number {
const value: number = asNumber(input);
return value * value;
}
square(10)
// 100
square()
// Error: Unable to cast undefined to number
square('10')
// Error: Unable to cast string to number
Type Casts are meant to primarily validate questionable values that are expected to be in a well defined structure. Such as network responses, interfacing with untyped JavaScript or reading data back from a file. If you are looking to validate a type, without throwing an error then take a look at Type Checks.
The standard type cast functions take a second optional parameter, which is a fallback value. In the situation that the input is Nullish
and the fallback parameter has been defined the function will return the fallback parameter instead of throwing. This is very helpful for validating the input of an optional value, and providing a default value.
import { asString } from 'ts-runtime-typecheck';
function printName (name: unknown) {
const value: string = asString(name, 'Dave');
console.log(`Hello ${value}, how are you today?`);
}
printName()
// Hello Dave, how are you today?
printName('James')
// Hello James, now are you today?
printName(42)
// Error: Unable to cast number to string
In the situation you want to check a value meets an Optional
type there exists an alternate function for each type cast. These take the form asOpt{TYPE}
. Unlike the standard functions they do not allow for a fallback value, but when a Nullish
value is passed in they will always emit undefined
. If the input is not Nullish
, then it behaves the same as the standard type casts. If the type condition is met then it emits the value, otherwise it will throw.
Type Checks take an unknown
value as an argument, and return a boolean
indicating if the given value matches the required type. These functions take the form is{TYPE}
. In the correct situation TypeScript is capable of refining the type of a value through the use of these functions and flow analysis, like the below example.
import { isNumber } from 'ts-runtime-typecheck';
export function printSq (value: unknown) {
if (isNumber(value)) {
// inside this block `value` is a `number`
console.log(`${value} * ${value} = ${value * value}`);
}
else {
// inside this block `value` is `unknown`
console.log('Invalid input', value);
}
}
In addition all relevant Type Checks have an alternate variant that take the form isOpt{TYPE}
. These variants return true if the value meets the given type or Nullish
.
import { isOptNumber } from 'ts-runtime-typecheck';
export function printSq (input: unknown) {
if (isOptNumber(input)) {
// inside this block `input` is `number | undefined | null`
const value = input ?? 1; // use nullish coalescing operator to ensure value is number
console.log(`${value} * ${value} = ${value * value}`);
}
else {
// inside this block `input` is `unknown`
console.log('Invalid input', value);
}
}
Type Coercion functions take an unknown
value as an argument, and convert it into a specific type. These functions take the format make{TYPE}
. Unlike the other functions this only works for small subset of types: number, string and boolean. They make a best effort to convert the type, but if the input is not suitable then they will throw an error. For instance passing a non-numeric string to makeNumber
will cause it to throw, as will passing a string that is not "true" | "false"
to makeBoolean
. While these functions will take any input value, this is to allow the input of values that have not been validated. The only valid input types for all 3 functions are number | string | boolean
. The intention here is to allow useful conversion, but prevent accidentally passing complex types.
There is an argument that makeString
could support using the toString
method of an object
, but the default toString
method returns the useless [object Object]
string. It is possible to detect if an object has implemented it's own toString
method, but is it correct to use it in this situation? That depends on the intention of the programmer. In the absence of a clear answer the line has been drawn at only accepting primitives.
import { makeNumber } from 'ts-runtime-typecheck';
makeNumber('80') // 80
makeNumber(80) // 80
makeNumber(true) // 1
makeNumber(false) // 0
makeNumber('hello') // Error: Unable to cast string to Number
makeNumber({
toString () { return 'hello' }
}) // Error: Unable to cast object to Number
Dealing with validating JSON values can often be frustrating, so to make it a little easier JSON specific types and checks are provided. Using the JSONValue
type in your code will ensure that TS statically analyses any literal values as serializable to JSON.
import type { JSONArray, JSONObject, JSONValue } from 'ts-runtime-typecheck';
// JSONArray is an Array of JSONValues
const a: JSONArray = [12, 'hello'];
// JSONObject is a Dictionary of JSONValues
const b: JSONObject = {
num: 12,
str: 'hello'
};
// JSONValue can be any of the following: JSONObject, JSONArray, string, number, boolean or null
const c: JSONValue = 12;
const d: JSONValue = new Error('hi'); // Type 'Error' is not assignable to type 'JSONValue'
For dynamic data isJSONValue
and asJSONValue
provide recursive type validation on a value.
Type Check and Type Casts are provided for JSONArrays
and JSONObjects
, with the caveat that they only accept JSONValues
. This is to avoid needing to recursively validate values which have already been validated.
import { asJSONValue, isJSONObject, isJSONArray } from 'ts-runtime-typecheck';
import type { JSONValue } from 'ts-runtime-typecheck';
function main (a: unknown) {
const obj: JSONValue = asJSONValue(a);
// obj: JSONValue
if (isJSONArray(obj)) {
// obj: JSONArray
}
else if (isJSONObject(obj)) {
// obj: JSONObject
}
else {
// obj: number | string | boolean | null
}
}
One other caveat of JSONValue
is that it does not guarantee that the value is not cyclic. It is not possible to serialize cyclic object with JSON.stringify
, but they are otherwise valid. Using isJSONValue
or asJSONValue
on a cyclic object will fail.
import { asJSONValue } from 'ts-runtime-typecheck';
import type { Dictionary } from 'ts-runtime-typecheck';
const almost_right: Dictionary = {};
almost_right.self = almost_right;
// BANG! this will fail, it recurses endlessly
const obj = asJSONValue(almost_right);
A common situation is that you have an Optional
value, with a well defined type. At a specific time it should be defined, but the type system is not aware of this. TypeScript will allow you to cast the value to a non-optional type using !
, but this is often discouraged in style guides. As an alternative solution you can use the asDefined
function, which removes the optionality from a type union. As with the other type casts this can take a fallback value, and will throw if the condition is not met. However, the output type matches the input type with Nullish
subtracted.
import { asDefined } from 'ts-runtime-typecheck';
function setup (useComplexType: boolean = false, complexInst?: ComplexType) {
if (useComplexType) {
const inst: ComplexType = asDefined(complexInst);
inst.doComplexThing();
}
else {
doSimpleThing();
}
}
Validating that a value is an array or dictionary is easy enough, but how about the type of the contents? asArrayOf
and asDictionaryOf
allow you to cast the elements of a collection using a user defined Type Check. For example, to cast to Array<string>
:
import { isString, asArrayOf } from 'ts-runtime-typecheck';
function main (obj: unknown) {
const asStringArray = asArrayOf(isString);
const arr: string[] = asArrayOfString(obj);
}
Or Array<Dictionary<number>>
:
import { isNumber, isDictionaryOf, asArrayOf } from 'ts-runtime-typecheck';
function main () {
const isDictionaryOfNumber = isDictionaryOf(isNumber);
const asArrayOfDictionaryOfNumber = asArrayOf(isDictionaryOfNumber);
const arr = asArrayOfDictionaryOfNumber([
{
a: 12,
b: 42
},
{
n: 90
}
]);
}
Validating the shape of an object using a combination of asDictionary
and other Type Casts specific to property types can be a bit verbose. To simplify this scenario you can use asStruct
. This function takes an InterfacePattern
that defines a specific structure and returns a new function that will cast an unknown value to that structure. An InterfacePattern
is a fancy name for a Dictionary
of Type Checks.
import { asStruct, isString, isOptString, isNumber } from 'ts-runtime-typecheck';
interface Item {
name: string;
value: number;
}
const asItem = asStruct({ name: isString, value: isNumber })
function main (obj: unknown) {
const item: Item = asItem(obj);
console.log(`${item.name} = ${item.value}`);
}
There is also a Type Check variant of the this function called isStruct
which works in a very similar way. As an InterfacePattern
is composed of Type Check functions it's possible to compose nested interface Type Checks.
import { asStruct, isString, isOptString, isNumber } from 'ts-runtime-typecheck';
interface Declaration {
item: Item;
description: Optional<string>
}
const isItem = isStruct({ name: isString, value: isNumber });
const asDeclaration = asStruct({ item: isItem, description: isOptString });
function main (obj: unknown) {
const { item, description } = asDeclaration(obj);
const comment: string = description ? `// ${description}` : '';
console.log(`${item.name} = ${item.value} ${comment}`);
}
When a value can be 2 or more types it is relatively easy to do Type Check.
import { isString, isArray } from 'ts-runtime-typecheck';
if (isString(a) || isArray(a)) {
// a: string | unknown[]
}
But you can't cast to that type, or pass it into a function like asArrayOf
or isStruct
which require a Type Check for their input. To do this you can use isUnion
or asUnion
. These functions take a variable number of Type Checks and produce a union of them.
import {
isString,
isArray,
isUnion,
asArrayOf
} from 'ts-runtime-typecheck';
const check = asArrayOf(isUnion(isString, isArray));
const b = check(['hello', [0, 1, 2], 'world']);
Under most scenarios you will know if a value is an instance of a given class. However, there are scenarios where this is not the case. For these situations you can use isInstance
or asInstance
to ensure you have the correct type.
import { isInstance } from 'ts-runtime-typecheck';
function print_error (err) {
if (isInstance(Error)(err)) {
print_string(err.message);
} else {
print_unknown(err)
}
}
When validating a value matches an interface it may be desirable to instead use isInstance
instead of isStruct
. While it doesn't provide the same guarantees it will often be significantly faster, as it does not perform a Type Check on each member to see that they exist and contain the right type of value.
Cast unknown
to string
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to number
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to Index
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to Indexable
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to boolean
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to Array<unknown>
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to Dictionary<unknown>
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to UnknownFunction
. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast Type | Nullish
to Type
, where Type
is a generic parameter. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast unknown
to JSONValue
. This function recursively validates the value, and hence will fail if given a cyclic value. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast JSONValue
to JSONObject
. Unlike asJSONValue
this does not perform recursive validation, hence it only accepts a JSONValue
so that the sub-elements are of a known type. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Cast JSONValue
to JSONArray
. Unlike asJSONValue
this does not perform recursive validation, hence it only accepts a JSONValue
so that the sub-elements are of a known type. Accepts an optional fallback value that is emitted if the value is nullish and fallback is defined.
Takes a Type Cast function for Type
and returns a new Type Cast function for Array<Type>
where type is a generic parameter. The emitted Type Cast function accepts an optional fallback value that is emitted if the value is nullish and fallback is defined. Refer to Array/Object of Type Casts for examples.
Takes a Type Cast function for Type
and returns a new Type Cast function for Dictionary<Type>
where type is a generic parameter. The emitted Type Cast function accepts an optional fallback value that is emitted if the value is nullish and fallback is defined. Refer to Array/Object of Type Casts for examples.
Takes an InterfacePattern
which is equivalent to Type
and returns a new Type Cast function for Type
, where Type
is an interface defined by the TypeAsserts
specified in the pattern. Refer to Validating interfaces for examples.
Takes a class (not a instance of a class) and returns a new Type Cast for an instance of that class.
Cast unknown
value to string | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to number | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to Index | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to Indexable | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to boolean | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to Array<unknown> | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to Dictionary<unknown> | undefined
. If value is Nullish
then return undefined
.
Cast unknown
value to UnknownFunction | undefined
. If value is Nullish
then return undefined
.
Takes a variable number of type checks as parameters <A>(...checks: TypeCheck<A>[])
and returns a new type cast that composes them into type cast for the union A
. This allows creating a cast for a type union by composing any existing type checks.
Identical to asUnion
but it the resulting cast returns A | null | undefined
.
Cast unknown
value to JSONValue | undefined
. If value is Nullish
then return undefined
.
Cast JSONValue | undefined
value to JSONObject | undefined
. If value is Nullish
then return undefined
.
Cast JSONValue | undefined
value to JSONArray | undefined
. If value is Nullish
then return undefined
.
Takes a Type Cast function for Type
and returns a new Type Cast function for Array<Type> | undefined
where type is a generic parameter. Refer to Array/Object of Type Casts for examples.
Takes a Type Cast function for Type
and returns a new Type Cast function for Dictionary<Type> | undefined
where type is a generic parameter. Refer to Array/Object of Type Casts for examples.
Takes an InterfacePattern
which is equivalent to Type
and returns a new Type Cast function for Type | undefined
, where Type
is an interface defined by the TypeAsserts
specified in the pattern. Refer to Validating interfaces for examples.
Takes a class (not a instance of a class) and returns a new Type Cast for a Optional instance of that class.
Takes an unknown
value and returns a boolean indicating if the value is of the type Dictionary<unknown>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type UnknownFunction
.
Takes an unknown
value and returns a boolean indicating if the value is of the type boolean
.
Takes an unknown
value and returns a boolean indicating if the value is of the type string
.
Takes an unknown
value and returns a boolean indicating if the value is of the type number
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Index
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Indexable
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Array<unknown>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type undefined
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Nullish
.
Takes an unknown
value and returns a boolean indicating if the value is not of the type Nullish
.
Takes a variable number of type checks as parameters <A>(...checks: TypeCheck<A>[])
and returns a new type check that composes them into union type check TypeCheck<A>
. This allows creating a test for a type union by composing any existing type checks. For inline code it will generally make sense to use logical OR operators instead of this, for example if ( isNumber(n) || isArray(n) ) {}
. This particular function is intended for when you wish to compose a type check or cast that contains a union, or create a library type check for a common union type.
Takes an unknown
value and returns a boolean indicating if the value is of the type JSONValue
.
Takes an JSONValue
value and returns a boolean indicating if the value is of the type JSONArray
.
Takes an JSONValue
value and returns a boolean indicating if the value is of the type JSONObject
.
Takes a Type Check function for Type
and returns a new Type Check function for Array<Type>
where Type is a generic parameter.
Takes a Type Check function for Type
and returns a new Type Check function for Dictionary<Type>
where Type is a generic parameter.
Takes an InterfacePattern
which is equivalent to Type
and returns a new TypeAssert
function for Type
, where Type
is an interface defined by the TypeAsserts
specified in the pattern. Refer to Validating interfaces for examples.
Takes a class (not a instance of a class) and returns a new Type Check for an instance of that class.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<Dictionary<unknown>>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<UnknownFunction>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<boolean>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<string>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<number>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<Index>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<Indexable>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<Array<unknown>>
.
Identical to isUnion
but it the resulting typecheck is TypeCheck<A | null | undefined>
.
Takes an unknown
value and returns a boolean indicating if the value is of the type Optional<JSONValue>
.
Takes an Optional<JSONValue>
value and returns a boolean indicating if the value is of the type Optional<JSONArray>
.
Takes an Optional<JSONValue>
value and returns a boolean indicating if the value is of the type Optional<JSONObject>
.
Takes an InterfacePattern
which is equivalent to Type
and returns a new TypeAssert
function for Optional<Type>
, where Type
is an interface defined by the TypeAsserts
specified in the pattern. Refer to Validating interfaces for examples.
Takes a Type Check function for Type
and returns a new Type Check function for Optional<Array<Type>>
where Type is a generic parameter.
Takes a Type Check function for Type
and returns a new Type Check function for Optional<Dictionary<Type>>
where Type is a generic parameter.
Takes a class (not a instance of a class) and returns a new Type Check for a Optional instance of that class.
Takes an unknown
value and converts it to it's textual representation. A value that cannot be cleanly converted will trigger an error.
Takes an unknown
value and converts it to it's numerical representation. A value that cannot be cleanly converted will trigger an error.
Takes an unknown
value and converts it to it's boolean representation. A value that cannot be cleanly converted will trigger an error.
A union of all the JSON compatible types: JSONArray
, JSONObject
, number
, string
, boolean
, null
.
An alias to Dictionary<JSONValue>
which can represent any JSON Object
value.
An alias to Array<JSONValue>
which can represent any JSON Array
value.
An alias to Record<string, Type>
where Type
is a generic parameter that default to unknown
. This type can be used to represent a typical key-value map constructed from a JS Object
. Where possible use Map
instead, as it is specifically designed for this purpose and has better protection against null errors in TS.
A union of the number
and string
types that represent a value that could be used to index an element within a JS Object
.
An alias to Record<Index, Type>
where Type
is a generic parameter that default to unknown
. This type can be used to represent an unknown key-value object that can be indexed using a number
or string
. It is intended to be used to ease the transition of JS project to TS. Where possible use Dictionary
or preferably Map
instead, as it is specifically designed for this purpose and has better protection against null errors in TS.
A union of undefined
and null
. Generally preferable to either null
or undefined
on non-validated input. However, be aware of varying behavior between these 2 types in JS around optional members, default parameters and equality.
A union of Type
and Nullish
where Type
is a generic parameter.
A stricter alternative to the type Function
. It accepts any number of unknown parameters, and returns an unknown value. Allowing you to reference an untyped function in a slightly safer manner. This does not provide any arity or type checks for the parameters.
Identical to UnknownFunction
in all ways but 1, it returns Promise<unknown>
instead.
An alias for a function that meets the requirements of TypeScript Type Guards. They take the format (value: unknown) => value is TYPE
. With the exception of specialist JSON checks all Type Checks conform to this type.
An alias for a Dictionary
of TypeAssert
functions. When used in conjunction with isStruct
or asStruct
they can validate an object
against the equivalent interface to the pattern.
unknown
.null | undefined
).T | undefined
union.null
in the type union.asOpt{TYPE}
is now TYPE | undefined
instead of Optional<TYPE>
( removes null from union )isStruct
and asStruct
that allow the inspection of a object to see if it meets a specific interface.isOpt{TYPE}
.asDefined
can longer accept null
as a fallback parameter.asIndexable
now accepts arrays.isIndexable
type check.TypeAssert
type publicly.InterfacePattern
type.isUnion
and isOptUnion
to allow checking if a value matches any type of a type union.asUnion
and asOptUnion
to allow casting a value to a type union.isArrayOf
and isOptArrayOf
to allow checking if a value is an array of a given type.isDictionaryOf
and isOptDictionaryOf
to allow checking if a value is a Dictionary of a given type.asArrayRecursive(asOptString)
to asArraryOf(isOptString)
or (similar) the output array may contain null
as the elements are no longer transformed by an inner cast ( optional cast methods normalize output to undefined
).isInstance
and isOptInstance
to allow checking if a value is an instance of a given class.asInstance
and asOptInstance
to allow casting a value to an instance of a given class.asRecord
, asOptRecord
, asRecordRecursive
and asOptRecordRecursive
have been renamed to asDictionary
, asOptDictionary
, asDictionaryOf
and asOptDictionaryOf
respectively.asArrayRecursive
and asOptArrayRecursive
have been renamed to asArrayOf
and asOptArrayOf
respectively.TypeAssert
to TypeCheck
FAQs
A collection of common types for TypeScript along with dynamic type cast methods.
The npm package ts-runtime-typecheck receives a total of 251 weekly downloads. As such, ts-runtime-typecheck popularity was classified as not popular.
We found that ts-runtime-typecheck demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.