Members and fields✎
Reading a field from a value whose type says what it holds, and what to use when it doesn't.
Reviewed
A value often holds other values, such as a table with string keys or an instance with properties. Two nodes read one out, and which you want depends on one question - Does anything know what is there?
| Node | Reads | When |
|---|---|---|
| Get Member | A field the type declares | The type says what it holds: a Declare Type's fields, a Roblox class's properties. The list is offered, and for a type this file declares, a name not on it is refused before the file is written. |
| Get Field | Any key you name | Nothing can promise what is in there: a dictionary filled and emptied as the program runs, or whatever require returns, which arrives untyped. |
A type you declared
A type is declared by a Declare Type node — at the top of the file or where it sits — and what it is written as decides whether it has members to offer. A table of fixed fields does; everything else is a type Luau understands and this cannot enumerate.
| Written as | Example | Members |
|---|---|---|
| Table of Fields | Rows in the Inspector: throttle, number | Each row, with its type. The ordinary case, and the one the editor checks as you type it. |
| Custom Luau, a table | { throttle: number, aim: Vector3 } | The same fields, read out of the text — so a type typed out by hand behaves as the rows do. |
| Custom Luau, anything else | "idle" | "driving", (number) -> string | None. There is no fixed field list to offer, and a Get Member on one is refused. |
| A dictionary type | { [string]: number } | None: the keys are the program's business. That is Get Field's case. |
| Type of a Value | typeof(Tuning) | None here. Luau resolves it; Roswaal does not follow it, so its members are Get Field's. |
The type's name is what travels. A Declare Local, a function's parameter, a variable or a Cast set to Input gives a pin typed Input, and every pin typed Input offers the same fields — the declaration is read wherever it sits in the file, including from inside a function.
The ordinary case: Input is a custom type that holds fields for throttle, steer and aim, each entered as a row in the declaration. The local variable is marked as the type, with the pill reading aim and passing on the resulting Vector3.
export type Input = { throttle: number, steer: number, aim: Vector3, } local input: Input = { throttle = 1, steer = 0, aim = Vector3.zAxis, } print(input.aim)
The result is typed as the field is. aim gives a Vector3 pin and throttle a number pin, so what comes out wires into a Vector3 node without a Cast.
A type written as Custom Luau — click its Definition to open it in the Code panel — behaves as the rows do, as long as what you wrote is a table of named fields. This is the shape to reach for when a field's own type is more than a name — { Player }, Model?.
export type Shot = { damage: number, from: Vector3 } local shot: Shot = { damage = 25, from = Vector3.zero } print(shot.damage)
A dictionary type, a union, a function type: Luau understands each of them, and none have a field list that anybody can write down. Get Member offers nothing and refuses a member on one — Get Field is the node, and the key is a pin you fill in or wire.
export type Scores = { [string]: number } local scores: Scores = { alice = 12, bob = 9 } print(scores.alice)
A type a module exports
A module's exported types are offered here too, under the name this graph writes them as: require Tank.Config as Config, and a value annotated Config.Tuning offers that type's fields. The fields are read from the graph that declares them, so renaming one there changes what is offered here.
Two files, one idea
local ReplicatedStorage = game:GetService("ReplicatedStorage") local Config = require(ReplicatedStorage.Tank.Config) local tuning: Config.Tuning = Config.tuning print(tuning.turnRate)
This graph uses both nodes, for different reasons. The module's own table is a value nothing here can describe — Roswaal does not read the other file's returns — so Config.tuning is a Get Field. What comes out is annotated as a type that is described, so turnRate off it is a Get Member.
Info
A Roblox instance
An instance's properties come from the engine, so they need no declaring. A node that names a class hands back that class — New Instance set to Part gives a Part — and a Part's properties are then what Get Member offers.
local part: Part = Instance.new("Part") if part.Anchored then end
Inherited properties are there too: Name and Parent come from Instance, and a Part offers them alongside its own. Get Service gives the service's own class, and the Find First Child and Ancestor nodes follow their Class Name, so each of those leads straight into a member without a cast first.
Warning
Finding one
| Gesture | What you get |
|---|---|
| Drag a wire out of a typed pin | That type's members in the node menu, under their own heading. Picking one places a Get Member already wired |
Type input. in either node search | Every member of everything this graph names — a variable, a local, a parameter. Picking one places the getter and the Get Member on it, wired |
| Select a Get Member | Its Member in the Inspector, as a list of what the wired type declares |
When there is no list
A table whose keys come and go while the program runs has no fixed members, and nothing offers any: that is Get Field, which takes the key as a pin and reads whatever is there. A key that is not a Luau name — a number, or a string with a space in it — is Get Field's as well, since t.my key is not something Luau can write.
Warning
Last reviewed 29 September 2026 by @neopolitans