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

fulltype

v0.0.11

Published

Introduce type schema, auto generated type, and dynamic check on parsing in Typescript

Downloads

4

Readme

Type Architect

Introduction

In Typescript, the type definition and the data definition live in different world. Data schema definition can be very useful when it comes to generate dynamically values. For example, to derive MongoDb validation rule or GraphQL schema directly from your data definitions. You need to define the type and the data schema (it breaks the DRY philosophy)

Type Architect is a library to design the shape of your data. It provides powerful tool to derive the type directly from the model of your data, and to parse JSON with the proper static type and a dynamic checking according to the given model. You data model is defined, so you can use it to derive other data schema like a mongo validation table

Installation

yarn install fulltype

Example

Here is an example with an user data model with a mongoDb ID:

import { ObjectId } from 'mongoDb';
import { typeArchitect, Type } from 'type-architect';

const userModel = typeArchitect.buildModel({
  kind: 'object',
  content: {
    _id: { kind: 'custom', content: 'ObjectId' },
    email: { kind: 'primitive', content: 'string' },
    name: { kind: 'primitive', content: 'string' },
    passwordHash: { kind: 'primitive', content: 'string' },
  },
} as const);
// "as const" is mandatory, Type Architecte can only work with const type

type User = Type<typeof userModel, { ObjectId: ObjectId }>;

The only prerequisites with Type Architect is that all model should be defined as const (with a const type).

You can easily parseJson with proper type (static type) and with dynamic type checking.

import { typeArchitect } from 'type-architect';

const userJson = `{
  "_id": "507f1f77bcf86cd799439011",
  "email": "[email protected]",
  "name": "NAME",
  "passwordHash": "qiyh4XPJGsOZ2MEAyLkfWqeQ"
}`;

// parsedUser is already typed with the type Type<typeof userModel, { ObjectId: ObjectId }>
const parsedUser = typeArchitect.parseJson({
  model: userModel,
  json: userJson,
  customMapping: { ObjectId: (idStr) => new ObjectId(idStr) },
});

Documentation

The model type

A model can be built with the function typeArchitect.buildModel.

The model type use an ADT style approach, each model looks like this:

{
  kind: ..., // kind of model
  content: ... // the actual content of the model
}

There are 5 differents model kind in Type Architect: 'primitive', 'constant', 'array', 'object', 'or, 'custom'.

'primitive' kind

The primitive kind allows you to represent primitive type.

For now, the supported primitives types are:

  • 'boolean'
  • 'date'
  • 'number'
  • 'string'
  • 'undefined'
  • 'void'

For example, for a model representing a string, we will have:

const primitiveModel = typeArchitect.buildModel({
  kind: 'primitive',
  content: 'string',
} as const);

'constant' kind

The constant kind allows you to represent constant. A constant will be represented by a set of possible string values.

For example, to represent the following constant : 'FREE' | 'PENDING' | 'DONE', we will have:

const constantModel = typeArchitect.buildModel({
  kind: 'constant',
  content: ['FREE', 'PENDING', 'DONE'],
} as const);

'array' kind

The array kind allows you to represent an array of some type. It is done by combining a model with an array model.

For example, if we want to represent an array of string, we will have:

const arrayModel = typeArchitect.buildModel({
  kind: 'array',
  content: {
    kind: 'primitive',
    content: 'string',
  },
} as const);

'object' kind

The object kind allows you to represent object. It is done by combining model in different fields with an objec model.

For example, if we want to define an object position with two fields, we will have:

const objectModel = typeArchitect.buildModel({
  kind: 'object',
  content: {
    positionX: {
      kind: 'primitive',
      content: 'number',
    },
    positionY: {
      kind: 'primitive',
      content: 'number',
    },
  },
} as const);

'or' kind

The or kind allows you to represent conjoction. It is done by combining two models.

For example, if we want to define an value which is boolean or a number, we will have:

const orModel = typeArchitect.buildModel({
  kind: 'or',
  content: [
    {
      kind: 'primitive',
      content: 'boolean',
    },
    {
      kind: 'primitive',
      content: 'number',
    },
  ],
} as const);

'custom' kind

The custom kind allows you to express type that can not be represented with the other structure of model. It can be usefull to express a model deriving from an existing class.

The content of a custom kind model is the name you want to give to this custom type.

For example, if we want to define the model of an error, we will have:

const objectModel = typeArchitect.buildModel({
  kind: 'custom',
  content: 'someError',
} as const);

If you want to compute the type of a model where there are custom kind model, you need to give a mapping of the custom kind model present from its name to an actual type:

type ObjectModelWithCustom = Type<typeof objectModel, { someError: Error }>;

In the same way, for JSON parsing, when there are custom kind model in your model, you need to provide a customMapping to check and map the parsed string to the proper type:

const jsonWithCustom = 'SOME ERROR TEXT';

const parsedObjectWithCustom = typeArchitect.parseJson({
  model: objectModel,
  json: jsonWithCustom,
  customMapping: { someError: (errorMessage) => new Error(errorMessage) },
});

buildModel

The typeArchitect.buildModel function allows to build model with the proper structure. Its parameter should always be define as a const type

Type

Type is a generic type which can derive a type from a model. It can take two parameters:

  • the type of the model to type: typeof yourModel (mandatory)
  • a CustomMapping for the custom kind present in the model. It should be the type of an object the name of the custom kind of the model as key and their actual type as value

parseJson

The typeArchitect.parseJson function allows you to parse a JSON according to a model. The parsed value is statically type to the type derived from the model. During the parsing, there will also be some dynamic check performed.

generate

The typeArchitect.generate function allows you to generate a random data from a model.

generateObject

The typeArchitect.generateObject function allows you to generate a random data from an object kind model. You can provide with the field parameter customFields specific value for some fields of the generated object.