This simplifies Scala type hierarchy which just removes “reference” type, and add a null/nullable concept for refs.
any -> value (number, string, object, array, union, null) -> bottom
See https://docs.scala-lang.org/tour/unified-types.html
any
type can take any value, including null
;let x: any = 123;
let y: any = "456";
let z: any = true;
let value: any = null;
let x: number = "123"; // error!
let y: string = 123; // error!
let z: null = true; // error!
Null is a special value type, with only one value is null
.
Nullable type (T?
) is just a synonym of union<T, null>
.
let t: null = null;
let t2: null = 123; // error!
T?
(nullable T) is same as union<T, null>
let t: number? = 1;
let t2: union<number, null> = t;
let t3: number? = t2;
let x: number = 1;
let x1: number? = x;
let x2: number = x1; // error!
let x: number = null; // error!
let x: union<number?, string?, null> = null;
let y: union<number, string, null> = x;
Union stands for multiple possible types for a value, makes the data structure more flexible.
let x: union<union<number, string>, union<string, boolean>> = 1;
let y: union<number, string, boolean> = x;
let x: union<any, number> = 1;
let y: union<any> = y;
union<T>
is same as T
which means union<..., any, ...>
is same as any
.
Nullable union is same as union<ts..., null>
, and vice versa.
let x: union<number, string>? = null;
let y: union<number, string, null> = y;
Object are structural compatible, and constrained by following rules:
let x : { a: number, b: string } = { a: 1, b: "2" } ;
let y : { a: number } = x;
let x : { a: number?, b: string } = { b: "1" }; // { a: null } omitted
let y : { a: number?, b: string? } = x;
let x : { a: { b: string? , c: number }, d: boolean } =
{ a: { c: 456 }, d: false }
let y : { a: { c: number? }?, d: boolean } = x;
let a: array<union<number, string, null>> = [123, '456', null];
let b: array<union<number, string>?> = a;
bottom
as data type.let v: bottom; // BOOM!