Hacker News new | past | comments | ask | show | jobs | submit login

> it features one of the most ergonomic type systems I have ever worked with.

This is surprising. Which other type systems have you worked with?




Yes, I found the ReScript/OCaml type system much more ergonomic.


Having worked with OCaml and F#, I find that TypeScript requires fewer changes to non-type code in response to changes to the types.

For instance, given `type T = { a: string; b: string; c: string }`, if I want to make `b` and `c` nullable but always provided together:

    // OCaml
    type TOpt = { a: string; bc: (string * string) option } 

    // TypeScript 
    type TOpt = T | { a: string; b: undefined; c: undefined }
With the TypeScript approach, code which worked with T still works with TOpt (only requiring an `if(x.b)` guard). With the OCaml approach, any code that accessed b or c needs to be rewritten.

The same applies to cases where an object can be in several different modes, but some properties are present in all modes. For example, an AST node can be a literal, identifier, binary operation, etc. but it always has a source location and an inferred type. In OCaml this has to be represented by either separating a "common properties" type from a "kind of node" union type:

    type node = { loc: location ; inferred_type: exprtype option ; kind: nodekind }
    and nodekind = Lit of string | Id of string | Unary of op * node
Or by repeating the common properties in all union type constructors:

    type node = Lit of location * exprtype option * string
              | Id of location * exprtype option * string
              | Unary of location * exprtype option * op * node
Both are tedious (although F# makes the second one slightly less tedious by allowing one to define computed properties on union types). By contrast, TypeScript allows you to have only one type:

    type NodeCommon = { loc: location; inferred_type: exprtype|undefined }
    type Lit = NodeCommon & { kind: "lit"; value: string }
    type Id = NodeCommon & { kind: "id"; value: string }
    type Unary = NodeCommon & { kind: "unary"; op: op; node: Node }
    type Node = Lit | Id | Unary




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: