1.1.0 • Published 3 years ago

@typeguards/core v1.1.0

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
3 years ago

TypeGuards

build Coverage Status NPM semantic-release Commitizen friendly Conventional Changelog

Runtime type checking library for TypeScript & JavaScript.

✨ Features

  • Provides runtime type validation.
  • Can derive static type from any type guard, thus types are never out of sync.
  • Supports nested type guards.
  • Supports almost all JS data types, including Promise, Proxy, DataView and typed arrays.
  • Package has 0 dependency.

📦 Installation

# npm
npm install @typeguards/core
# yarn
yarn add @typeguards/core

🔨 Usage

Basics

import T from '@typeguards/core'

T.Number.validates(1) // true
T.Number.validates('1') // false
T.Optional(T.String).validates('1') // true
T.Optional(T.String).validates(undefined) // true
T.Optional(T.String).validates(1) // false

// Custom type guard
const Range = T.Number.config({
  // Custom validation function
  validate: value => typeof value === 'number' && value > 0 && value < 3,
})
Range.validate(0) // false
Range.validate(1) // true
Range.validate(2) // true
Range.validate(3) // false

Schema

import type { Static } from '@typeguards/core'
import T, { createSchema } from '@typeguards/core'

const Age = T.Number.config({ validate: v => typeof v === 'number' && v >= 0 })

// Custom schema
const JobSchema = T.Schema({
  title: T.String,
  salary: T.Nullable(T.Number),
})

// Use closure to use type guard directly & prevent naming conflicts with JS built-in objects
const PersonSchema = createSchema(({ Boolean, String, Number, Array, Optional, Union }) => ({
  name: String,
  age: Age,
  alive: Boolean,
  address: Optional(String),
  // Support complex nested type guard
  favorites: Array(Union(String, Number)),
  // Support nested schema
  job: JobSchema,
}))

// Support static type derivation, thus type is never out of sync
const person: Static<typeof PersonSchema> = {
  name: 'John Doe',
  age: 23,
  alive: true,
  address: undefined,
  favorites: ['cat', 'dog', 7],
  job: {
    title: 'Dreamer',
    salary: null,
  },
}

PersonSchema.validate(person) // true
PersonSchema.validate({ ...person, address: undefined }) // true, because address is optional
PersonSchema.validate({ ...person, name: undefined }) // false
PersonSchema.validate({ ...person, age: '23' }) // false

const CatSchema = T.Partial(T.Pick(PersonSchema, ['name', 'age', 'alive']))
// Equivalent to Partial<Pick<PersonType, 'name' | 'age' | 'alive'>>
type Cat = Static<typeof CatSchema>

CatSchema.validate(person) // false
CatSchema.validate({ name: 'Baby', age: undefined }) // true

// Retrieve Schema definition
const catDefinition = CatSchema.definition() // { name: String, age: Age, alive: Boolean }
// Retrieve Indexed access type definition, which is a type guard in this case
const CatName = CatSchema.definition('name') // T.String
CatName.validate('str') // true
catDefinition.name.validate('str') // true

Transformer (Experimental Feature)

import T from '@typeguards/core'

// Customize transformation function
const Name = T.String.config({ transform: val => `${val} Jr.` })
const Alive = T.Boolean.config({ transform: val => val ?? true })
const Person = T.Partial(T.Schema({ name: Name, alive: Alive }))

const john = { name: 'John' }
Person.validate(john) // true
const johnJr = Person.transform(john) // { name: 'John Jr.', alive: true }

🛡️ List of type guards

namedescription
Boolean
StringBoolean"true" | "TRUE" | "false" | "FALSE" | "1" | "0"
Number
NaNNaN
PositiveNumberA number value that's greater than 0
NegativeNumberA number value that's less than 0
BigInt
PositiveBigIntA BigInt value that's greater than 0
NegativeBigIntA BigInt value that's less than 0
StringNumberA string whose value is a number, such as "0", "-1", "3.333"
String
NonEmptyStringA string that's not empty even after trimming
Symbol
Undefinedundefined
Nullnull
ObjectAn object (Any object will qualify as long as typeof obj === 'object')
RegExp
Map
WeakMap
Set
WeakSet
Promise
Proxy
Date
StringDateA correctly formatted date string, such as "1996-07-23", "1996/07/23", "1996 Jul", "1996"
Array
StringArrayA string whose value is an array separated by delimiter "," (delimiter is customizable)
ArrayBuffer
SharedArrayBuffer
DataView
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array
BigInt64Array
BigUint64Array
FunctionA function
SchemaA plain object
OptionalT | undefined
NullableT | null
NeverEquivalent of TypeScript never type
UnknownEquivalent of TypeScript unknown type
AnyEquivalent of TypeScript any type
RecordEquivalent of TypeScript Record type
PartialEquivalent of TypeScript Partial type
RequiredEquivalent of TypeScript Required type
PickEquivalent of TypeScript Pick type
OmitEquivalent of TypeScript Omit type
NonNullableEquivalent of TypeScript NonNullable type
UnionEquivalent of TypeScript union type
ConstEquivalent of TypeScript const assertion
GeneratorFunctionRequires ES6/ES2015 or later
GeneratorRequires ES6/ES2015 or later
AsyncFunctionRequires ES8/ES2017 or later

📜 License

Apache License 2.0