๐Ÿ”’ The new way to do types in typescript.

Overview

Nominal

The right way to do types in typescript.

Installation

npm install nominal-types

yarn install nominal-types

pnpm install nominal-types

Usage

Basic

The most immediate benefit of nominal types is preventing confusion between two types. In regular Typescript you run into this problem:

type Minutes = number
type Seconds = number
const minutesToSeconds = (minutes: Minutes) => minutes * 60

const seconds: Seconds = 420
// uh-oh, we can use Minutes and Seconds interchangeably
minutesToSeconds(seconds)

Nominal types solve this problem

import { Nominal, nominal } from 'nominal-types';

type Minutes = Nominal<'Minutes', number>;
type Seconds = Nominal<'Seconds', number>;

const minutesToSeconds = (minutes: Minutes) => minutes * 60

// You can directly type cast or use nominal.make
const seconds = nominal.make<Seconds>(420)
const minutes = 1337 as Minutes

// doesn't work, yay type safety
minutesToSeconds(seconds)
// does work!
minutesToSeconds(minutes)

Another example

You can use nominal types to give your code even better type-safety guarantees.

This goes beyond just type-safety, it's a performance optimization: once you know the array is sorted, you never have to sort it again. This is enforcing that at a type level.

type SortedArray<T> = Nominal<'sortedArray', Array<T>>

const sort = <T>(arr: Array<T>): SortedArray<T> => arr.sort()

const binarySearch = <T>(
  sorted: SortedArray<T>,
  search: T
): number | undefined  => {
    /* ... */
}

const regularArray = [1, 7, 2, 3, 6, 9, 10, 4, 5]
// won't work
binarySearch(regularArray, 2)
// will work
binarySearch(sort(regularArray), 3)

This is also known as Refinement types

Composing types

We can actually make this a bit crazier, we can compose nominal types

type SortedArray<T> = Nominal<'sortedArray', Array<T>>

const sort = <T>(arr: Array<T>): SortedArray<T> => arr.sort() as SortedArray<T>

const nonEmpty = <T>(arr:Array<T>):NonEmptyArray<T> => arr.filter(Boolean) as NonEmptyArray<T>

type NonEmptyArray<K, T extends Array<K>> = Nominal<'nonEmptyArray', T>;
type NonEmptySorted<T> = NonEmptyArray<T, SortedArray<T>>;

const binarySearch = <T>(sorted: NonEmptySorted<T>): T => {
  let foo = sorted[0]
  return foo
}

// won't work
binarySearch(regularArray)
// still won't work
binarySearch(sort(regularArray))

binarySearch(nonEmpty(sort(regularArray)))

Examples

More examples in examples folder, you can also see them typed on replit.

Example Link
basic https://replit.com/@CryogenicPlanet/Nominal#basic.ts
sorting https://replit.com/@CryogenicPlanet/Nominal#sort.ts
composing https://replit.com/@CryogenicPlanet/Nominal#composing.ts
safeRecords https://replit.com/@CryogenicPlanet/Nominal#safeRecord.ts

Credits

You can read more about this https://zackoverflow.dev/writing/nominal-and-refinement-types-typescript

Inspiration from Ghosts of Departed Proofs (Functional Pearl)

You might also like...

String Types For io-ts

io-ts-strings String types for io-ts npm install io-ts-strings Currently implemented types: Alpha AlphaNumeric Ascii Base32, Base58, Base64 BIC(SWIFT

Mar 13, 2022

Basic types & utilities for Strapi v4 and plugin creators

Strapi v4 - Types & utilities Basic set of types and utilities for Strapi v4 and plugins creators A developers goodie for Strapi Headless CMS which pr

Oct 14, 2022

well yes, but can you do it in types?

Yes, but can you do it in types? A collection of challenges which you complete in solely the type system. Everyone knows you can write code to do thin

Oct 27, 2022

jQuery pop-up script displaying various types of content in corner of browser

Corner Popup v1.30 Fully customizable pop-up box created to display all types of messages in corner of your browser. Website: https://espritdesign.pl/

Nov 27, 2022

You can easily create the horizontal timeline with two types by using this jQuery plugin.

You can easily create the horizontal timeline with two types by using this jQuery plugin.

jQuery.Timeline V2 You are able to easily create two types of horizontal timeline with this jQuery plugin. Report bug ยท Request feature ยท Blog Table o

Dec 9, 2022

Functions for testing the types of JavaScript values, cross-realm. Has testers for all standard built-in objects/values.

@suchipi/is Functions for testing the types of JavaScript values, cross-realm. Has testers for all standard built-in objects/values. Usage import { is

Sep 8, 2022

Minimalistic configuration for TS to only extend JS with types. No TS features, no bundling. Readable maintainable code after compilation.

Minimalistic configuration for TS to only extend JS with types. No TS features, no bundling. Readable maintainable code after compilation.

ts-guideline Minimalistic configuration for TS to only extend JS with types. No TS-scpecific features, no bundling. Readable maintainable code after c

Dec 22, 2022

100% type-safe query builder for node-postgres :: Generated types, call any function, tree-shakable, implicit type casts, and more

โš ๏ธ This library is currently in alpha. Contributors wanted! tusken Postgres client from a galaxy far, far away. your database is the source-of-truth f

Dec 29, 2022

Catalogist is the easy way to catalog and make your software and (micro)services visible to your organization in a lightweight and developer-friendly way.

Catalogist is the easy way to catalog and make your software and (micro)services visible to your organization in a lightweight and developer-friendly way.

catalogist ๐Ÿ“š ๐Ÿ““ ๐Ÿ“’ ๐Ÿ“– ๐Ÿ”– The easy way to catalog and make your software and (micro)services visible to your organization through an API You were a pe

Dec 13, 2022
Comments
  • Wrong link in About

    Wrong link in About

    Cool project! Noticed a small typo in the About section:

    The link currently points to a 404: https://zackoverflow.dev/writing/nominal-types-typescript

    Should point to: https://zackoverflow.dev/writing/nominal-and-refinement-types-typescript

    opened by christianboyle 1
  • [Question]What's the different between this project and ts-opaque ?

    [Question]What's the different between this project and ts-opaque ?

    This project seems to be a simplified version of that one, from what I read you seem to be using similar approaches to make the magic happen. I haven't read the entire code so I am probably wrong. But anyway can the nominal type be used as a better/newer/shorter/lighter alternative to opaque type, since they are conceptually similar ?

    opened by yw662 1
  • Shorter Implementation of Nominal

    Shorter Implementation of Nominal

    const M = Symbol();
    
    export type Nominal<Name extends string, Type> = Type & {
      readonly [M]: [Name];
    };
    
    

    Works with all the examples mentioned in readme.md

    check it out :

    https://codesandbox.io/s/nominal-types-l8k9ti?file=/src/nominal.ts

    help wanted 
    opened by MananTank 3
Owner
Modfy
Organization responsible for building modfy.video
Modfy
Compile-time tests for types. Useful to make sure types don't regress into being overly-permissive as changes go in over time.

expect-type Compile-time tests for types. Useful to make sure types don't regress into being overly-permissive as changes go in over time. Similar to

Misha Kaletsky 82 Jan 8, 2023
Variant types in Roblox TypeScript - Ported from Vanilla TypeScript

Variant (for Roblox) This is a roblox typescript variant (heh, pun) of Variant. See the Variant documentation on how to use Variant. A variant type is

Australis 2 Jun 3, 2022
Simple "everyday CRUD" Postgres queries with perfect TypeScript types

Crudely Typed Simple "everyday CRUD" Postgres queries with perfect TypeScript types. Zero dependencies. Designed to work with pg-to-ts and node-postgr

Dan Vanderkam 26 Dec 26, 2022
๐Ÿงฉ TypeScript utility type in order to ensure to return only properties (not methods) containing values in primitive types such as number or boolean (not Value Objects)

?? TypeScript Primitives type TypeScript utility type in order to ensure to return only properties (not methods) containing values in primitive types

CodelyTV 82 Dec 7, 2022
A little utility type package that allows you to access the current TypeScript version from your types.

@phryneas/ts-version A little utility type package that allows you to access the current TypeScript version from your types. import { TSVersion } from

Lenz Weber-Tronic 11 Sep 4, 2022
๐ŸŽŠ A Collection of TypeScript types for the Kirby CMS

kirby-fest A collection of TypeScript types to work with Kirby, mainly in the context of the Kirby Query Language. Setup # pnpm pnpm add -D kirby-fest

Johann Schopplich 5 Nov 22, 2022
Opinionated collection of TypeScript definitions and utilities for Deno and Deno Deploy. With complete types for Deno/NPM/TS config files, constructed from official JSON schemas.

Schemas Note: You can also import any type from the default module, ./mod.ts deno.json import { type DenoJson } from "https://deno.land/x/[email protected]

deno911 2 Oct 12, 2022
TSServer plugin & Utilities for "expanding" TypeScript types

ts-expand-type This repo provides a TS Server plugin which amends quick info to include the fully "expanded" type. "Expanded" means that object inters

Max Stoumen 6 Nov 20, 2022
Quick way to start a new TypeScript/Next.js/Firebase web app ๐Ÿ˜ผ

create-crash-app Template repo to quickly set up an opinionated, strict config, typesafe Next.js project. Get started with create-crash-app by running

Diego Dorantes-Ferreira 5 Oct 28, 2022
Different Types of Monsters Card of Popular anime. Build in React tech.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: ya

Abhishek Tiwari 5 Mar 19, 2022