Skip to content

Dkendal/Newtype

Repository files navigation

Newtype

Newtype is a programming language for type level programming in typescript.

Why

Typescript has a powerful typesystem, so powerful that it's turing complete1. One is fully capable of writing a JSON parser 2 using only the type system, ignoring the question of if this is a good idea or not. In spite of this power, typescript's type system grammar is packed full of impicit rules 34, and becomes quite unweildy with any significant length.

Installing from source

git clone https://github.com/dkendal/newtype
cd newtype
stack build
stack install

Grammar and syntax

Newtype borrows a good deal of syntax and ideas from Haskell and Idris. Statements are only allowed at the top of the document, not unlike typescript.

Primitive types

Primitive types are the same as in Typescript.

any
unknown
object
string
number
bigint
boolean
null
undefined
never

Statements

Imports

import "./foo-bar" (Foo, Bar)

exports

Members are exported separately from their definition.

provide (Foo, Bar)

Type definition

type True = true

Interfaces

interface ArrayBufferTypes where
  ArrayBuffer : ArrayBuffer

Expressions

Object literals, properties

Generic type application

Angle brackets and commas, and parens are omitted in newtype. Expressions may be parenthesized to disambiguate.

type Foo = Pick Bar "a" | "b"
type Foo = Pick<Bar, "a" | "b">

Mapped types

Mapped types5 use set builder notation6.

{ Value : Key <- Type }

Infer prefix operator

? replaces the infer keyword.

?Type

Conditional types

Newtypes makes it much easier to write conditional types7

All expressions below compile to an equivalent typescript A extends B ? Then : Else expression.

Operator

Newtype introduces a number of binary operators for type comparison.

  • A <: B is equivalent to A extends B, read as extends-left.
  • A :> B is equivalent to B extends A, read as extends-right.
  • A == B
  • A != B

It also introduces a single prefix operator to negate a condition

  • not A <: B

If-Then-Else

if A <: B
then C
else D

If the else branch is omitted, it is assumed to be never.

Boolean infix operators

Expressions can be combined using and, and or.

if A <: B then if C <: D then E

Can be rewritten as:

type T =
  if A <: B and C <: D
  then E

Which is equivalent to:

type T = A extends B ? (C extends D ? E : never) : never;

Case statements

type T =
  case A of
    string -> 1
    object -> 2
    _ -> never

Which is equivalent to:

type T = A extends string ? 1 : A extends object ? 2 : never;

Related projects

Footnotes

Footnotes

  1. https://github.com/Microsoft/TypeScript/issues/14833

  2. https://github.com/jamiebuilds/json-parser-in-typescript-very-bad-idea-please-dont-use

  3. https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types

  4. Basically any question answered by the infamous and prolific jcalz has answered on Stackoverlow: https://stackoverflow.com/users/2887218/jcalz

  5. https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

  6. https://en.wikipedia.org/wiki/Set-builder_notation#In_programming_languages

  7. https://www.typescriptlang.org/docs/handbook/2/conditional-types.html

About

type level programming that compiles to typescript.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published