struct is an actual implementation
// explicit
struct Foo { name: String };
const foo: Foo = { name: "bob" };
// ^= struct Foo { name: String };
// implicit
const bar = { age: 18 };
// ^= anonymous struct { age: number };
type is anything that matches the given type
type Foo = { name: String };
fn bar(f: Foo) {
stdout.println(f.name);
// f = type { name: String };
}
const person = { name: "Bob", age: 18 };
// ^= anonymous struct { name: String, age: number };
bar(person); // ok
const restaurant = { name: "Snackbar", location: "1st street, some place" };
// ^= anonymous struct { name: String, location: String };
bar(restaurant); // ok
Allow generic functions over types with fields
fn foo(a: impl { name: String }) {
stdout.print(a.name);
}
// or:
fn foo<A>(a: A)
where A: impl { name: String }
{
stdout.print(a.name);
}
// or:
type FooArg = { name: String };
fn foo(a: FooArg) {
}
Allow multiple where conditions per function
type foo<T>(t: T)
where T: { name: String },
T: SomeInterface
{
stdout.print(a.name);
}
Allow remapping types by key
struct Foo {
name: String,
}
type Bar = {
[for key in Foo]: i32,
};
// ^= type Bar = { name: i32 }
Allow appending fields & types
type Foo = { name: String };
type Bar = { age: i32 } & Foo;
// ^= type Bar = { name: String, age: i32 };
Allow removing fields with never
type Foo = { name: String, age: i32 };
type Bar = Foo & {
age: never
};
//^ type Bar = { name: String };
Getters & setters
struct Foo {
get name() { return "Foo"; }
set name(value: String) { stdout.print("New name is", value); }
}
underscore variables are private
struct Foo {
_name: String;
}
Example for making a struct readonly:
struct Foo {
name: String
}
type Bar<T> = {
_inner: T,
[for key in T]: get() -> T[key] {
return _inner[key];
}
}