RuntypeScript
Type system is the value system
Types and values are mixed with each other, so using the terms type and value interchangeably can get confusing (because they aren't different things in this language). Since these value/type hybrids work more like types than values, we will refer to them only as types on this page.
nil
Nil represents nothing. It is returned by a function when nothing is returned explicitly.
false, true
False and true are the results of comparison operators and can be used as operand for logical operators.
boolean
Boolean is a union of false and true.
string
String is a union of every possible string literal.
String literals
String literals are enclosed in double quotes. You can make use of the following escape sequences in a string literal:
- \\ (backslash)
- \" (double quote)
- \n (line feed)
- \t (tab)
- \r (carriage return)
number
Number is a union of every possible number literal.
Number literals
Number literals are double presicion floating-point. Only decimal literals are supported (no hexadecimal or exponentials).
Typed array
Typed array is defined by specifying its element type. Type array is a union of every possible tuple, for which every element is assignable to typed array's element type. You can turn any type into a typed array by appending a pair of square brackets after the type.
const array_of_number = number[]; const array_of_zero_or_foo = (0 | "foo")[]; const array_of_array = any[][];
Tuple
Tuples are arrays of types and are indexed by number literals.
const tuple = [number, string]; const also_tuple = [0, 1, 2, fn () nil {}, boolean, [number, "foo"]];
Tuples are passed by reference and are mutable.
Object
Objects can hold multiple properties and are indexed by string literals.
const empty_obj = {}; const simple_obj = { foo: "bar", baz: string[] }; const nested_obj = { foo: {}, baz: [{}] };
Signatures
Signatures are specified by a list of argument types and a return type. A signature is a union of every possible function assignable to that signature.
const binary_sig = sig (any, any) any; const filter_sig = sig (any[], sig (any) boolean) any[];
Signatures never contain names of arguments.
Functions
Every function is its own distinct type tied to its literal.
const concat = fn (a: string, b: string) string { return a + b; };
Function arguments are not constants and can be reassigned inside the function body. A function will capture its outside scope.
There are intrinsic functions in this language, which are global constants and their function bodies are implemented in the interpreter itself instead of the language. They cannot be created by language users.
Unions
Unions represents a type, to which many other types are assignable. You can create unions using "|" operator. Unions do not nest (a union of unions collapses into a single union) and are immutable.
any
Any is a union of every possible type in this language, including itself.
Deliteralization
Deliteralization is a transformation of types, that is performed to determine the declared type when none was provided. You can use unary "~" operator to perform the same process yourself. Deliteralization rules:
- false becomes boolean
- true becomes boolean
- string literals become string
- number literals become number
- tuples become typed arrays of union of all tuple's elements deliteralized
- object become objects with their properties deliteralized
- functions become signatures with equivalent argument and return types
- unions become a union of its types deliteralized
- other types are left intact
Assignability
Assignability is a process that determines whether a type can be assigned to a variable's declared type. You can use binary "extends" operator to perform the same process yourself. Assignability rules:
- a union is assignable to a type when all union's types are assignable to that type
- only nil is assignable to nil
- only false is assignable to false
- only true is assignable to true
- false, true and boolean are assignable to boolean
- string and string literals are assignable to string
- only identical string literals are assignable to string literals
- number and number literals are assignable to number
- only identical number literals are assignable to number literals
- a typed array is assignable to other typed array if its element type is assignable to other typed array's element type
- a tuple is assignable to a typed array if all its elements are assignable to typed array's element type
- an object is assignable to other object if every property of other object also exists in the object and types of the object properties are assignable to correspoding types of the other object properties
- a signature is assignable to other signature if every argument of the signature is assignable to corresponding other signature's arguments and other siganture's return type is assignable to the signature return type
- a function is assignable to a signature if its deliteralization is assignable to the signature
- only identical functions (by reference) are assignable to functions
- a type is assignable to a union if its assignable to any of union's types
- every type is assignable to any