Step 3 of 14, updated

Types and use

A system's types are written once, in its Types.shot, and every file of the folder names them with no import. use replaces the require line.

You'll learn a Types file, how files see it, imports, and use.

A types file

struck ShotScript writes it for youhighlighted new in ShotScript
Luau todayTypes (a ModuleScript)
export type Reason = "Pickup" | "Shop"export type Entry = {	Amount: number,	Reason: Reason,}return {}
ShotScript65 linesWallet/Types.shot
public type Reason = "Pickup" | "Shop"public type Entry = {	Amount : number,	Reason : Reason,}
  • public type may leave the system; internal type stays in the folder.
  • Order doesn't matter: a type may use one defined below it.
  • Only imports, type definitions and their docs go here (later pages add events and rules).

Using the types

Luau todayCoins (a ModuleScript)
--!strictlocal Types = require(script.Parent.Types)type Entry = Types.Entrylocal SUFFIX = " coins"local Coins = {}function Coins.Format(amount: number): string	return tostring(amount) .. SUFFIXendfunction Coins.Line(entry: Entry): string	local s = Coins.Format(entry.Amount)	return s .. " for " .. entry.Reasonendreturn Coins
ShotScript1311 linesWallet/Coins.shot
types script.Parent.Typeslocal SUFFIX = " coins"module Coins = {	function Format(amount : number) : string		return tostring(amount) .. SUFFIX	end	function Line(entry : Entry) : string		local s = Coins.Format(entry.Amount)		return s .. " for " .. entry.Reason	end}
What it compiles toWallet/Types.luau
--!strict
if true then return {} end

--[[$public]] export type Reason = "Pickup" | "Shop"

--[[$public]] export type Entry = {
	Amount : number,
	Reason : Reason,
}

--[[$public]] export type Coins = {
	Format : (amount : number) -> string,
	Line : (entry : Entry) -> string,
}
  • Each compiled file starts with an export type line per type of the folder: you never write those.
  • Every class, module and func of the folder is a type too: Coins is one, with no declaration.
  • A type in a signature (a parameter, a return, a field) belongs in Types.shot; one written inside a file works only in that file.

Tip Another system's types come in through this folder's Types.shot, and nowhere else: import Entry, Reason from @shot.Wallet, or import * from @shot.Wallet. An import gives a type, not a value: require the system to call it.

Use

use writes the local and the require for you, named after the last part of the path:

Luau todayServer (a Script)
local ReplicatedStorage =	game:GetService("ReplicatedStorage")local Coins = require(	ReplicatedStorage.Shot.Wallet.Coins)print(Coins.Line({	Amount = 25,	Reason = "Pickup",}))
ShotScript86 linesInit/Server.shot
@server enableduse @shot.Wallet.Coinsprint(Coins.Line({	Amount = 25,	Reason = "Pickup",}))
What it compiles toInit/Server.server.luau
--!strict
local Coins = require(script.Parent.Parent.Wallet.Coins)

print(Coins.Line({
	Amount = 25,
	Reason = "Pickup",
}))

A bare name, use Coins, finds the nearest Coins: this folder's files and folders, then the folder above, up to the project root. Init/ is beside Wallet/, not above it, so from there the tool asks for the path:

$ shot check
./Init/Server.shot:3   use Coins: no Coins in this folder or any folder above it (use looks at each folder's own files and folders, up to the project root); it is in Wallet: use @shot.Wallet.Coins
1 errors in 1 file (4 files checked, 2.4 s)

Checked

The union is a real type. A misspelt reason, Reason = "Pikup", is an error at its line:

$ shot check
./Init/Server.shot:5:18   TypeError: Expected this to be exactly 'Entry', but got '{| Amount: number, Reason: "Pikup" |}' caused by: Property 'Reason' is not compatible. Expected this to be exactly '"Pickup" | "Shop"', but got '"Pikup"'; none of the union options are compatible
1 errors in 1 file (4 files checked, 2.4 s)

Spelt right, it checks and runs:

$ shot run Hello
==== Hello
[server print] 25 coins for Pickup
[client:Ana print] client started

==== summary
  Hello          OK  (2 lines, 0 errors, 0.1s virtual)
1 of 1 scenario(s) passed
Try it

Add "Daily" to Reason in Types.shot and use it in Init/Server.shot: no import, no alias line, and shot check passes. Then take "Daily" out again: page 10 adds it for real.