luau/rfcs/type-namespaces.md
2023-08-05 10:57:11 -04:00

2.1 KiB

Type Namespaces

Summary

Add user syntax to define namespaces for type declarations.

Motivation

When working with multiple modules in a project, it is common for users to use a separate module solely for containing type declarations to avoid having cyclic requires in the typechecker. One of these modules may look like this:

export type ShapeType = "Triangle" | "Square" | "Circle"

export type ObjectParams = {
	Name: string,
	Shape: ShapeType,
	Position: Vector3
}

return nil

An added benefit of this pattern is that, when the above module is required, a namespace is created for the exported types in the module's name:

local Types = require("Types")

local MyShape: Types.ShapeType = "Circle"

local Object = {
	Name = "MyObject",
	Shape = MyShape,
	Position = Vector3.zero
} :: Types.ObjectParams

This RFC aims to streamline defining type namespaces like the above without having to use modules as well as allowing for multi-dimensional namespaces to help organize large projects (i.e., Types.Shape.ObjectParams).

Design

Namespaces could be added to any type declaration via a dot to discern between space name and type name:

type Space.Name = number

local Foo: Space.Name = 1

This syntax could also allow for nested namespaces as well as generated namespaces for exported types:

export type Types.Space.Name<A, B> = A | B

Drawbacks

This syntax design may introduce repetition for multiple types as it is by declaration-basis. For example:

export type Space.Foo = number | string
export type Space.Bar = "Hello" | "World"
export type Space.Baz = boolean

Mistypes could confuse users as they create a new namespace for the type:

export type Space.A = number
export type Spaze.B = string

Nested spaces could also confuse users since namespaces could be mingled with actual types:

local Foo: Space.Foo = 1
local Bar: Space.Bar.Foo = true

Alternatives

Using the in keyword instead:

type Name in Space = number

Having overarching syntax for namespaces:

export Space
	type foo = number,
	type bar = string