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

typonomy

v0.30.0

Published

Type Management Utilities for TypeScript

Downloads

377

Readme

Typonomy

Type Management Utilities for TypeScript

npm version

Purpose

TypeScript allows developers to apply strict yet flexible type checking on top of an implicit (and very messy) JavaScript type paradigm. Combined with JavaScript's flexible functions, TypeScript becomes a very readable, capable and safe functional programming language. Typonomy exists to help achieve even greater readability, safety, and convenience by adding additional helper types and functions.

Design Goals

  • Make it convenient to avoid any; it's unsafe and unnecessary.
    • Type guards already exist or are easy to create.
  • Support and encourage explicit typing.
    • But make types easily and safely inferrable to help reduce verbosity.
    • Code is more readable when the types are well-known.
  • Use consistent names.
    • Try to reuse common vernacular when feasible.
    • Invent reasonable names when necessary, and explain what these new names mean.
  • Support functional over object-oriented where possible.
    • Classes are mostly just objects/interfaces with function properties. The rest doesn't matter much.
    • Use explicit types to demonstrate functional programming concepts.
  • Locate code for ease of development.
    • Consuming code can import submodules directly vs the entire module.
    • Keep submodules small and focused.
    • No circular submodule dependencies.
  • Support the most common collections and iteration patterns
    • Arrays, objects, Record<K,V>.
    • reduce, map, and forEach-style functions for the above.
  • Don't Repeat Yourself.
    • Reuse code internally.
  • Document everything clearly and explicitly.
  • Unit test everything.
    • The unit tests themselves become both documentation and usage examples.
  • Strict type checking.
  • Strict linting.

Example Uses

To demonstrate the types and type safety, these examples use more explicit typing than is typically necessary.

Short Circuit Iteration

import { Break, mapArray, type IndexedMapper } from "typonomy"
// value and index have inferred safe types.
const mapper: IndexedMapper<number, string> = (value, index) => {
  if (index === 2) throw Break
  return `${index}:${value}`
}
const mapped = mapArray([3, 5, 7, 11], mapper)
// `mapped` is `["0:3", "1:5"]`; 7 and 11 never get mapped.

Explicit and Safe Nullish Handling

import type { Nullable, Optional, Possible, Reducer } from "typonomy"
import { appendExplicit, isNull, isString, isUndefined, or, reduceArray, typeGuard } from "typonomy"

const possibleStrings: Array<Possible<string>> = [
  "An explicit value",
  null,
  undefined,
]

const isNullableString = typeGuard<Nullable<string>>(or(isString, isNull))
const filterUndefined: Reducer<Nullable<string>[], Possible<string>, number> = (state, value, _index) => {
  if (isNullableString(value)) state.push(value)
  return state
}
// [ "An explicit value", null ]
const nullableStrings = reduceArray<Nullable<string>[], Possible<string>>(possibleStrings, filterUndefined, [])

// "Optional" is a synonym for "may be undefined", and comes from the notion of optional parameters and properties.
const isOptionalString = typeGuard<Optional<string>>(or(isString, isUndefined))
const filterNull: Reducer<Optional<string>[], Possible<string>, number> = (state, value, _index) => {
  if (isOptionalString(value)) state.push(value)
  return state
}
// [ "An explicit value", undefined ]
const optionalStrings = reduceArray<Optional<string>[], Possible<string>>(possibleStrings, filterNull, [])

// "Explicit" excludes null and undefined. `appendExplicit` already does this.
const filterNullish: Reducer<string[], Possible<string>, number> = appendExplicit<string>
// [ "An explicit value" ]
const strings = reduceArray<string[], Possible<string>>(possibleStrings, filterNullish, [])

Put Single Values and Arrays on Equal Terms

import type { Optional, Reducer, Some } from "typonomy"
import { addMore, isExplicit, isPlural, reduceSome } from "typonomy"


const countStrings: Reducer<number, Optional<string>, number> = (state, value) => state + (isExplicit(value) ? 1 : 0)
let someStrings: Some<string> = "One String"
// howManyStrings = 1
let howManyStrings = reduceSome(someStrings, countStrings, 0)

const manyStrings = addMore(someStrings, "Another string")
someStrings = manyStrings
// howManyStrings = 2
howManyStrings = reduceSome(someStrings, countStrings, 0)

if (isPlural(someStrings)) {
  const first: Optional<string> = manyStrings[0]
}
else {
  // It isn't, but it could have been if we'd done this before addMore().
  const str: string = someStrings
}

Installation

You can install Typonomy using npm, yarn, or pnpm:

npm install typonomy
yarn add typonomy
pnpm add typonomy

Documentation

See the API Documentation

Modules

Typonomy includes three kinds of JavaScript module format. The process for achieving this is inspired by this blog post from SenseDeep. This library uses ESBuild for constructing each module platform.

ES Module

Exports all code as an ECMAScript Module, suitable for import:

import * as typonomy from 'typonomy'

You can also import submodules:

import * as array from 'typonomy/array'

ES Modules are typically used:

  • In browser-based applications.
  • In applications that use a JS bundler system (ex: Bundler, Bun, Webpack, ESBuild, Vite, etc).
  • In modern Node.js applications.

CommonJS / Node module

Exports all code as a CommonJS, suitable for require.

const typonomy = require('typonomy')

You can also require submodules:

const array = require('typonomy/array')

CommonJS modules are typically used by older Node.JS applications.

Browser script.

Exports all code as a ES6 script suitable for inclusion in browsers. The code is wrapped in an Immediately invoked function expression (or "IIFE").

<script src='typonomy/dist/browser/index.js'>

You can also include submodules:

<script src='typonomy/dist/browser/array.js'>

Browser scripts are typically used by older web browser-based applications.

Issues and Discussion

Please feel free to propose any fixes, additions, modifications, or clarifications at the GitHub Issues for the project. Pull requests and forks are welcome for consideration for include into the main project.

License

Typonomy is licensed under the MIT License.