0.3.5 • Published 3 years ago

newtype-ts v0.3.5

Weekly downloads
27,297
License
MIT
Repository
github
Last release
3 years ago

build status npm downloads

Installation

To install the stable version:

npm i newtype-ts

Note. newtype-ts depends on fp-ts and monocle-ts, starting from 0.3.0 you must install both fp-ts and monocle-ts manually (fp-ts and monocle-ts are listed in peerDependency)

Motivation

A common programming practice is to define a type whose representation is identical to an existing one but which has a separate identity in the type system.

type USD = number
type EUR = number

const myamount: USD = 1

declare function change(usd: USD): EUR
declare function saveAmount(eur: EUR): void

saveAmount(change(myamount)) // ok
saveAmount(myamount) // opss... this is also ok because both EUR and USD are type alias of number!

Usage

Newtypes

Let's define a newtype for the EUR currency

import { Newtype, iso } from 'newtype-ts'

interface EUR extends Newtype<{ readonly EUR: unique symbol }, number> {}

// isoEUR: Iso<EUR, number>
const isoEUR = iso<EUR>()

// myamount: EUR
const myamount = isoEUR.wrap(0.85)

// n: number = 0.85
const n = isoEUR.unwrap(myamount)

declare function saveAmount(eur: EUR): void

saveAmount(0.85) // static error: Argument of type '0.85' is not assignable to parameter of type 'EUR'
saveAmount(myamount) // ok

By definition a "newtype" must have the exact same runtime representation as the value that it stores, e.g. a value of type EUR is just a number at runtime.

For the Iso type, see the monocle-ts documentation.

Refinements

An Integer is a refinement of number

import { Newtype, prism } from 'newtype-ts'

interface Integer extends Newtype<{ readonly Integer: unique symbol }, number> {}

const isInteger = (n: number) => Number.isInteger(n)

// prismInteger: Prism<number, Integer>
const prismInteger = prism<Integer>(isInteger)

// oi: Option<Integer>
const oi = prismInteger.getOption(2)

declare function f(i: Integer): void

f(2) // static error: Argument of type '2' is not assignable to parameter of type 'Integer'
oi.map(f) // ok

For the Prism type, see the monocle-ts documentation.

Builtin refinements

  • Char
  • Integer
  • Negative
  • NegativeInteger
  • NonNegative
  • NonNegativeInteger
  • NonPositive
  • NonPositiveInteger
  • NonEmptyString
  • NonZero
  • NonZeroInteger
  • Positive
  • PositiveInteger
import { NonZero, prismNonZero } from 'newtype-ts/lib/NonZero'

// a total function
const safeDivide = (numerator: number, denominator: NonZero): number => {
  return numerator / prismNonZero.reverseGet(denominator)
}

// result: Option<number>
const result = prismNonZero.getOption(2).map(denominator => safeDivide(2, denominator))

TypeScript compatibility

The stable version is tested against TypeScript 3.5.1

newtype-ts versionrequired typescript versionrequired fp-ts versionrequired monocle-ts version
0.33.5.1+2.0.0-rc.6+2.0.0-rc.1+
<= 0.2.42.8+1.0.0+1.0.0+

Performance

const double = n => n * 2
const doubleEUR = eurIso.modify(double)

Test double(2) vs doubleEUR(eurIso.wrap(2))

Results (node v8.9.3)

double x 538,301,203 ops/sec ±0.45% (87 runs sampled)
doubleEUR x 536,575,600 ops/sec ±0.27% (87 runs sampled)

Recipes

How to lift a function

const double = (n: number): number => n * 2

// doubleEUR: (s: EUR) => EUR
const doubleEUR = eurIso.modify(double)

Documentation

closet-viewer@closet-viewer/closet-viewer@everything-registry/sub-chunk-2266@viamedici-spc/configuratorauth-14testcafe-reporter-dashboardtestcafe-reporter-dashboard-devextremetestcafe-reporter-dashboard-testverdad@docmaps/sdk@cambrianone/camb-client@body-link/schemasio-ts-docoptstart-slicemachinets-aerodata-francets-endpoint-avengerthreat-model-managertreeqlite-http-server@arthurgubaidullin/nx-embed-dependencies@agiledigital/jiralint-lib@bitgo/public-types@bitgo/identity-token@0x706b/morphicyl-ddd-tsts-shareduse-font-metricsvelitlaborum@guardian/grid-client@hsiwe/schema-types-generator@futureverse/sylo-notifications-sdk@futureverse/sylo-protocol-sdk@isomorphic-typescript/ts-monorepo@metrika/charts@metrika/elastic-charts@mhoc/synthesize@marlowe.io/wallet@marlowe.nicolas/language-core-v1@marlowe.nicolas/legacy-adapter@marlowe.nicolas/legacy-runtime@marlowe.tmp/language-core-v1@marlowe.tmp/legacy-adapter@marlowe.tmp/legacy-runtime@marlowe.io/adapter@marlowe.io/language-core-v1@marlowe.io/runtime-core@marlowe.io/runtime-lifecycle@marlowe.io/runtime-rest-client@matechs/aio@nibus/core@navch/codec@nll/api-codegen-ts@epicallan/money-ts@monaxlabs/aspen-sdk@monaxlabs/cambium@monaxlabs/gen@monaxlabs/phloem@io-sign/io-sign@jmorecroft67/repository@imtbl/imx-link-types@imtbl/imx-sdk@qdev/utils-ts@ryb73/datalocker-api-types@prismicio/editor-fields@prismicio/types-internal@prismicio/mocks@projectdiscovery/interactsh@projectdiscovery/interactsh-cli@projectdiscovery/interactsh-client@projectdiscoveryio/interactsh@projectdiscoveryio/interactsh-cli@novastar/native@nvoy/base@nvoy/react-sdk@pagopa/cloudgaap-commons-ts@slicemachine/manager@slicemachine/adapter-sveltekit@shingo/describe2ts@slicemachine/adapter-nuxt@slicemachine/adapter-nuxt2@slicemachine/adapter-next@simspace/trout@resolve-js/eventstore-base@rockset/core@rockset/dev-server@stableness/wabble@squiz/dxp@squiz/dxp-climoney-tsopenapi-io-tspatch.comsannha-main-service-corenaznanihilsitreify-tsquidemnatusimx-sdk-alterguestbook-webio-interfacemarlowe-language-core-v1-txpipemarlowe-runtime-lifecycle-txpipe
0.3.5

3 years ago

0.3.4

5 years ago

0.3.3

5 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.4

6 years ago

0.2.3

7 years ago

0.2.2

7 years ago

0.2.1

7 years ago

0.2.0

7 years ago

0.1.3-rc

7 years ago

0.1.2

7 years ago

0.1.1

7 years ago

0.1.0

8 years ago

0.0.1

8 years ago