npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

schemable-ts-types

v0.0.4

Published

This package exposes io-ts-types built for use with Schema and Schemable in io-ts.

Downloads

8

Readme

schemable-ts-types

Exposes an extended Schemable typeclass SchemableExt with types inspired by io-ts-types, and validators.js.

Build Status NPM Version Coverage Status Vulnerabilities License

Table of Contents

Disclaimer

This library is in its nascent stages (< 1.0.0) and still has a lot of work ahead before it's at feature parity with io-ts-types, or validators.js.

Contributing

Test Coverage

This library currently has 100% jest coverage, contributions are highly encouraged and we should seek to maintain this high level of test coverage. Send over a PR!

Combinator Module Structure

Schemable combinator modules must have a unique name and can be found in the folder whose primitive they extend, i.e. string, number, or date. A Schemable combinator module must export Decoder, Eq, Guard, TaskDecoder, and Type instances (named exactly), along with type aliases: SchemableParams, SchemableParams1, and SchemableParams2C which are the types of the exported Decoder, etc instances with the HKT/Kind type argument for that particular instance. Optionally, combinator modules can export convenience functions to convert to stronger types, i.e. ISODateString to SafeDate with the assumption that the guard function (isISODateString) matches the strength of the target type.

Generating SchemableExt/Instances

Create a new combinator file using yarn generate:template [string | number] [NameOfCombinator]. Note: the name of the new combinator must be unique, and begin with a capital letter.

Once the new combinator modules are in place, run yarn generate:schemables and the ts script will update the typeclass instances and SchemableExt module with the newly created combinators. Don't forget to add tests!

Generating Documentation

Our docs pages are automatically generated whenever a PR is merged into the main branch, so the following step is optional. If you want to manually re-generate the documentation pages, use yarn docs. This command uses docs-ts and JSDoc-style annotations to parse code comments for metadata about each module.

Installation

Uses fp-ts, and io-ts as peer dependencies. Read more about peer dependencies at nodejs.org.

Yarn

yarn add schemable-ts-types

NPM

npm install schemable-ts-types

Documentation

Schemable types explained

The problem:

At present there is no way* in vanilla Typescript to derive domain typeclasses from domain types. Languages like Haskell, Purescript, and Rust support this functionality out of the box. With the older io-ts system you would have a domain declaration that looks like the following.

*(Note: ts-plus seeks to extend Typescript with this functionality and more)

import * as t from 'io-ts'

export const User = t.type({
  name: t.string,
  email: t.string,
  age: t.number,
})

export type User = t.TypeOf<typeof User>

Elsewhere in your package you could consume the User type using User.decode(/* Some unknown data structure */), which would guarantee that the runtime type (if value was a Right value) conforms to the expected data structure.

The more recent development in io-ts splits t – a collection of combinators which construct a class of Decoders/Encoders – into distinct modules, Decoder, Encoder, Eq, etc. Using this newer system presents a challenge, as you can no longer get Decoder, Encoder in a unified class with a single definition.

import * as D from 'io-ts/Decoder'
import * as Eq from 'io-ts/Eq'
import * as G from 'io-ts/Guard'

export type User = {
  name: string
  email: string
  age: number
  id: string
}

export const decodeUser: D.Decoder<User> = D.struct({
  name: D.string,
  email: D.string,
  age: D.number,
  id: D.string,
})

export const eqUser: Eq.Eq<User> = Eq.struct({
  name: Eq.string,
  email: Eq.string,
  age: Eq.number,
  id: Eq.string,
})

export const guardUser: G.Guard<User> = G.struct({
  name: G.string,
  email: G.string,
  age: G.number,
  id: G.string,
})

This works well and is type safe. But it comes with a big downside: if we need to change something, it is necessary to change it in four different places.

The solution: Schema / Schemable

With Schemable, you first provide instructions (Schema) to construct a domain type, and then provide a way to interpret instructions (Schemable).

The example above can be refined to the following with Schema and Schemable:

import { interpreter, make, TypeOf } from 'io-ts/Schema'
import * as D from 'io-ts/Decoder'
import * as Eq from 'io-ts/Eq'
import * as G from 'io-ts/Guard'

const UserSchema = make(S =>
  S.struct({
    name: S.string,
    email: S.string,
    age: S.number,
    id: S.string,
  })
)

export type User = TypeOf<UserSchema>

export const decodeUser = interpreter(D.Schemable)(UserSchema)

export const eqUser = interpreter(Eq.Schemable)(UserSchema)

export const guardUser = interpreter(G.Schemable)(UserSchema)

And with this, the structure of domain types and operators come from a single source, making future maintenance and extension trivial.

The value of an extended Schemable

With an extended schemable typeclass you have the powerful features of io-ts-types (restricted to the older Type system) and validators.js (written in javascript, and more difficult to adopt in a purely functional environment) with a modern domain type declaration system, and the power of fp-ts.

Let's refine our User type.

import { D, Eq, G, SC } from 'schemable-ts-types'

const UserSchema = SC.make(S =>
  S.struct({
    name: S.NonemptyString,
    email: S.Email,
    age: S.Natural,
    id: S.UUID({ version: 5 }),
  })
)

export type User = SC.TypeOf<UserSchema>

export const decodeUser = SC.interpreter(D.Schemable)(UserSchema)

export const eqUser = SC.interpreter(Eq.Schemable)(UserSchema)

export const guardUser = SC.interpreter(G.Schemable)(UserSchema)

And now we can guarantee that a user's email will conform to RFC 5322, their id will be a proper UUID-v5, and their age will not be negative.

Currently supported modules:

| primitive | refinement | | --------- | ------------------------- | | Date | SafeDate.ts | | generic | optionFromExclude.ts | | generic | optionFromNullable.ts | | generic | optionFromUndefined.ts | | number | Int.ts | | number | Natural.ts | | number | NegativeFloat.ts | | number | NegativeInt.ts | | number | NonNegativeFloat.ts | | number | NonPositiveFloat.ts | | number | NonPositiveInt.ts | | number | PositiveFloat.ts | | number | PositiveInt.ts | | string | ASCII.ts | | string | Base64.ts | | string | Base64Url.ts | | string | BigIntString.ts | | string | BtcAddress.ts | | string | CreditCard.ts | | string | EmailAddress.ts | | string | Hexadecimal.ts | | string | HexColor.ts | | string | HslColor.ts | | string | IntString.ts | | string | ISODateString.ts | | string | JWT.ts | | string | NaturalString.ts | | string | NegativeFloatString.ts | | string | NegativeIntString.ts | | string | NonemptyString.ts | | string | NonNegativeFloatString.ts | | string | NonPositiveFloatString.ts | | string | NonPositiveIntString.ts | | string | PositiveFloatString.ts | | string | PositiveIntString.ts | | string | RGB.ts | | string | UUID.ts |