@tilua/parser 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,13 +13,12 @@ the same one either way.
13
13
  |---|---|
14
14
  | [`@tilua/compiler`][compiler] | building a project to one Luau file |
15
15
  | [`@tilua/language-server`][server] | editor support over LSP |
16
- | [`@tilua-types/roblox`][roblox], [`@tilua-types/lua`][lua], [`@tilua-types/sunc`][sunc] | the globals a project may use |
16
+ | [`@tilua-types/roblox`][roblox], [`@tilua-types/sunc`][sunc] | the globals a project adds to Lua's |
17
17
  | `@tilua/parser` | this: tokens, AST, scopes, types |
18
18
 
19
19
  [compiler]: https://www.npmjs.com/package/@tilua/compiler
20
20
  [server]: https://www.npmjs.com/package/@tilua/language-server
21
21
  [roblox]: https://www.npmjs.com/package/@tilua-types/roblox
22
- [lua]: https://www.npmjs.com/package/@tilua-types/lua
23
22
  [sunc]: https://www.npmjs.com/package/@tilua-types/sunc
24
23
  [vscode]: https://marketplace.visualstudio.com/search?term=tilua
25
24
 
@@ -75,19 +74,23 @@ Neither analysis mutates the AST; both return side tables.
75
74
 
76
75
  ## Projects
77
76
 
78
- **No globals are built in** — not `print`, not `string`, not `game`. Only the
79
- language's own utility types are (`Partial`, `Pick`, `Omit`, `Record`,
80
- `ReturnType`, `Truthy`, ...; see `PRELUDE_SOURCE`). A project lists the type
81
- libraries it uses in `tilua.config.json`, the way TypeScript uses `@types/*`:
77
+ **Lua's standard library is built in**, as JavaScript's is in TypeScript:
78
+ `print`, `pairs`, `pcall`, `string`, `math`, `table`, `os`, `coroutine` and
79
+ `console` are there in every file with nothing listed (see
80
+ `STANDARD_LIBRARY_SOURCE`), and so are the language's own utility types
81
+ (`Partial`, `Pick`, `Omit`, `Record`, `ReturnType`, `Truthy`, ...; see
82
+ `PRELUDE_SOURCE`). What a host adds — Luau's and Roblox's `game`, `task`,
83
+ `Instance` — a project lists in `tilua.config.json`, the way TypeScript uses
84
+ `@types/*`:
82
85
 
83
86
  ```bash
84
- npm i -D @tilua-types/roblox # Luau + Roblox; or @tilua-types/lua on its own
87
+ npm i -D @tilua-types/roblox # Luau + Roblox
85
88
  ```
86
89
 
87
90
  ```jsonc
88
91
  // tilua.config.json
89
92
  {
90
- "types": ["roblox"], // and what it depends on: @tilua-types/lua
93
+ "types": ["roblox"], // on top of Lua's standard library
91
94
  "paths": { "@shared/*": ["src/shared/*"] }, // import aliases, as in tsconfig
92
95
  "sourceMap": "sourcemap.json" // a Rojo sourcemap, or null
93
96
  }
@@ -103,7 +106,13 @@ npm i -D @tilua-types/roblox # Luau + Roblox; or @tilua-types/lua on its
103
106
  matches every installed type library it fits (`"@tilua-types/*"`), in name
104
107
  order. A relative path (`"./types"`, `"./defs.d.tilua"`) loads the project's
105
108
  own definitions. A type library's own type-library dependencies load first;
106
- one that is not installed is an error.
109
+ one that is not installed is an error. `"lua"` — `@tilua-types/lua`, where
110
+ the standard library used to be — loads nothing: it is already there, and
111
+ a library that still depends on it does not bring it in twice.
112
+ - **`noLib`** — `true` leaves the standard library out, as TypeScript's
113
+ `noLib` does: no `print`, no `string`, only what `types` declares. For a
114
+ host with none of Lua's, or a library of one's own in its place. With it,
115
+ `"lua"` in `types` loads that package as an ordinary library.
107
116
  - **`paths`** — tsconfig rules: an exact pattern wins, then the `*` pattern
108
117
  with the longest prefix; targets resolve from `baseUrl` (default: the
109
118
  config's folder).
@@ -111,6 +120,11 @@ npm i -D @tilua-types/roblox # Luau + Roblox; or @tilua-types/lua on its
111
120
  follow it, and a file the tree maps gets its own `script`, so
112
121
  `script.Parent.Remotes` is typed. A `.tilua` file matches the Luau file of
113
122
  the same path.
123
+ - **`target`** and **`output`** — the compiler's: which Lua to emit for
124
+ (`"luau"`, the default, or `"lua51"`), and how many files to write
125
+ (`"single"`, the default; `"chunks"`, which also writes a file for what only
126
+ an `import()` reaches; or `"modules"`, one file per module). The parser only
127
+ checks them.
114
128
 
115
129
  | function | does |
116
130
  |---|---|
@@ -118,6 +132,7 @@ npm i -D @tilua-types/roblox # Luau + Roblox; or @tilua-types/lua on its
118
132
  | `loadConfig(path, host?)` | read and check one config |
119
133
  | `resolveTypeLibraries(config, host?)` | the `.d.tilua` files to load, in order |
120
134
  | `moduleCandidates(from, specifier, config?)` / `resolveModulePath(...)` | what an `import` means |
135
+ | `importExpressions(program)` | every `import("...")` written in a file |
121
136
  | `sourceMapTypes(text, path, { classes })` | the tree's types, and `scriptFor(file)` |
122
137
 
123
138
  Every problem comes back as `{ file, message, line, column }`, pointing into
@@ -236,6 +251,23 @@ is what a JavaScript arrow is for.
236
251
 
237
252
  **Declarations** — `const` and `let` only; Lua's `local` is gone.
238
253
 
254
+ What a `let` is first given is its type from then on, as in TypeScript:
255
+ `let n = 1` holds numbers, and `n = "a"` is an error. Only a name that starts
256
+ out holding nothing — `let x`, `let x = nil` — takes the type of whatever is
257
+ put in it later. A `let` declared with a type and no value (`let x: number`)
258
+ cannot be read until every way to the read has assigned it — `Variable 'x' is
259
+ used before being assigned` — unless its type admits `nil`. A function
260
+ written in between may read it: it runs later, when it is called.
261
+
262
+ **`n++` and `n--`** are `n += 1` and `n -= 1`: statements, as Luau's compound
263
+ assignments are, so they give no value and cannot be written inside an
264
+ expression. They apply to anything `+=` does — `t.count++`, `xs[i]--` — and
265
+ are checked as it is: the operator has to apply, and what it gives has to fit.
266
+ `--` is also how a comment starts, so `n--` is the decrement only where the
267
+ dashes touch the name (or the `]`) before them and nothing but the end of the
268
+ line, a `;`, a `}` or a comment follows; `n-- note` is still `n` and a
269
+ comment. `++n` is reported, with the spelling tilua uses.
270
+
239
271
  **Functions** — `function name() { ... }` declares `name` in the enclosing
240
272
  scope; like a TypeScript function declaration it cannot be reassigned.
241
273
  `const` and `let` do not apply to functions. `function T.name()` and
@@ -277,16 +309,40 @@ brings in names that are types and nothing else: unlike TypeScript, using one
277
309
  as a value is an error, and only type positions — `typeof A` included — may
278
310
  name it. Compiled code keeps no trace of it.
279
311
 
312
+ `import("./m")` is an expression: the module's exports as one value — what
313
+ `import * as M from "./m"` names `M` — read where the expression runs rather
314
+ than before the file does. The module is loaded the first time anything asks
315
+ for it, and the value comes back at once: there is no promise to wait on. The
316
+ path has to be a string literal, since which module it is must be known when
317
+ the project is built. On a line of its own, `import("./setup")` loads the
318
+ module for what it does. `importExpressions(program)` lists every one in a
319
+ file.
320
+
280
321
  **Methods of strings, arrays and tables** — a value answers to the methods
281
- its metatable's `__index` has, written with `:`:
322
+ its metatable's `__index` has. They are members, as a JavaScript object's
323
+ are: read with `.`, a method is a function whose first parameter is its
324
+ `self`, handed to it as any argument is. `:` hands it over for you, as Lua's
325
+ always has:
282
326
 
283
327
  ```luau
284
- const long = names:filter(n => #n > 3):map(string.upper)
285
- print(names:join(", "), text:trim(), text:upper())
328
+ const long = names:filter(n => n.length > 3):map(n => n:upper())
329
+ print(names.join(names, ", "), text.trim(text), "abc":upper())
286
330
  const point = { x: 1, y: "up" }
287
331
  const [x, y] = point:values() -- [number, string]
332
+ const join = names.join -- (self: string[], separator?: string) => string
288
333
  ```
289
334
 
335
+ `modes.includes(s)` leaves the `self` out, and is reported as that: call it
336
+ with `:`. The other way round, `o:f(x)` on a function that takes no receiver
337
+ would hand it `o` as `x`, and is reported too. `Stack.push(s, 1)`, which
338
+ passes the receiver by hand, is an ordinary call.
339
+
340
+ **`length`** — `xs.length` is how many a list holds and `text.length` a
341
+ string's length: Luau's `#`, which tilua does not have (`#xs` is an error that
342
+ says to write `xs.length`). A tuple's is known: `[number, string]` has length
343
+ `2`. A table with a `length` of its own is that member, and a class that
344
+ declares `__len` answers what `__len` does.
345
+
290
346
  Strings, arrays and tables are the language's own, so their metatables are
291
347
  too: the prelude declares them, in tilua, and they are there with no type
292
348
  library at all. A string's is Lua's (`upper`, `sub`, with one value where Lua
@@ -294,7 +350,12 @@ answers several: `find` is an array) plus the JavaScript-shaped ones (`trim`,
294
350
  `startsWith`, ...); an array's is JavaScript's (`filter`, `map`, `join`, ...),
295
351
  with Lua's indices — the first element is 1, `indexOf` answers `nil` rather
296
352
  than -1 — and `push`, `pop`, `shift`, `unshift`, `sort` and `reverse` change
297
- the array. A table's are `keys`, `values` and `entries`, which answer a tuple
353
+ the array. Looking for a value is not adding one, so `includes` and `indexOf`
354
+ take any value, not only one the array's type already holds — and `includes`
355
+ is a guard: `if (modes:includes(s))` narrows `s` to a mode. `concat` may join
356
+ arrays of other types (`(T | U)[]`). The ones that only read take a read-only
357
+ list too (`readonly T[]`, what `as const` makes), as TypeScript's
358
+ `ReadonlyArray` does; the ones that change it do not. A table's are `keys`, `values` and `entries`, which answer a tuple
298
359
  in the order the table's type wrote its members, not `string[]` as
299
360
  JavaScript's `Object.keys` does; the analyzer supplies that order as
300
361
  `ObjectKeys<T>`, `ObjectValues<T>` and `ObjectEntries<T>`. A member of a
@@ -302,7 +363,7 @@ value's own with the same name is what a call reaches, and a class instance,
302
363
  which has a metatable of its own, has none of them.
303
364
 
304
365
  No Lua array or table really has these methods, so the compiler lowers each
305
- call into its own runtime (`names:filter(f)` becomes `array.filter(names, f)`);
366
+ call into its own runtime (`names.filter(f)` becomes `array.filter(names, f)`);
306
367
  a string's Lua methods stay plain method calls.
307
368
 
308
369
  A library adds to a metatable by declaring the same target again, and a
@@ -358,8 +419,8 @@ such as `print(x)`, and `globalValue` for a global read as a value, such as
358
419
  hook is asked about it. A runtime can read `__LINES__`, the bundle's line map
359
420
  (`nil` outside a bundle), to turn a line Luau reports back into a place in the
360
421
  project. One that answers with a new array wraps it in `__ARRAY__(...)`, which
361
- writes it down as an array for `typeof`. `console:log`, `print` and `error` in `@tilua-types/lua` are built on
362
- these hooks.
422
+ writes it down as an array for `typeof`. The compiler's own lowering of the
423
+ standard library — `console:log`, `error`, `pcall` — is built on these hooks.
363
424
 
364
425
  **A `(` that starts a line** continues the statement above it, as in Lua and
365
426
  in JavaScript — `const v = map[key]` followed by `("A"):upper()` is one
@@ -368,6 +429,53 @@ write `;` before the `(` when a new statement was meant.
368
429
 
369
430
  **Object types** — `{ name: T, name?: T, [K]: V }`, and a name that is not an
370
431
  identifier is quoted, as in the literal: `{ "Respawn After Kill": boolean }`.
432
+ An index signature may name its key as TypeScript does, `[key: string]: V`, and
433
+ its key may be a template literal: `` { [`on${string}`]: Handler } `` takes every
434
+ `onX`, and an object literal with any other key is excess. A string or a list
435
+ fits a shape that names what it answers to: `"abc"` is a `{ length: number }`.
436
+ Members are separated by `,`, `;` or a line break, and may be written the
437
+ other ways TypeScript writes them:
438
+
439
+ ```luau
440
+ type Counter = {
441
+ readonly id: number
442
+ step(by: number): this -- a method: (self: this, by: number) => this
443
+ reset?(): nil -- an optional one
444
+ get total(): number -- read-only, unless a `set` is written too
445
+ set label(value: string)
446
+ (n: number): string -- calling the value; several are overloads
447
+ new (seed: number): Counter -- what its `new` makes: { new: (seed: number) => Counter }
448
+ }
449
+ ```
450
+
451
+ A method is called with `:`, as a class's methods are: its first parameter is
452
+ the receiver, typed `this`, so `counter:step(1)` hands `counter` over and
453
+ `counter.step(1)` is the missing argument it is. A signature with no return
454
+ type returns `nil`. Calling the value and having members too is the functions
455
+ and the members together — Lua builds such a value with a `__call` metatable.
456
+
457
+ **Interfaces** — `interface Name<T> extends A, B<T> { ... }`, with the members
458
+ an object type takes. It is a type alias for the bases and the members
459
+ together, with what TypeScript adds: two interfaces of one name are one, their
460
+ members merged (a method written in each is an overload set), and a member
461
+ that does not fit the one it replaces in a base is reported. `export
462
+ interface` exports it, as `export type` does.
463
+
464
+ ```luau
465
+ interface Named { name: string }
466
+ interface Greeter extends Named {
467
+ greet(other: Named): string
468
+ }
469
+ class Person implements Greeter {
470
+ name = "Ada"
471
+ function greet(other: Named): string { return `hi ${other.name}` }
472
+ }
473
+ ```
474
+
475
+ **`this` in a type** — TypeScript's polymorphic `this`: the value a member is
476
+ read from. A method that returns `this` returns whatever it was called on, so
477
+ `Builder.new():add(1):done()` keeps the subclass's members through the chain.
478
+ Inside the class it is the instance.
371
479
 
372
480
  **Optionality** — there is no `T?` shorthand. `?` in type position always
373
481
  belongs to a conditional type, and in expression position to a ternary or an
@@ -390,6 +498,29 @@ ternary. Parentheses end a chain. A chain cannot be assigned to (`a?.b = 1` is
390
498
  an error). A chain that got through narrows what it tested: inside
391
499
  `if (part?.Parent)`, and `if (part?.Name == "Door")`, `part` is not nil.
392
500
 
501
+ **`??`** — `a ?? b` is `a`, or `b` where `a` is nil; `b` is read only then.
502
+ Unlike `a or b` a `false` stays, which is what a `boolean | nil` wants:
503
+ `settings.enabled ?? true`. As in TypeScript it does not mix with `and` or
504
+ `or` without parentheses.
505
+
506
+ **`in`** — `"key" in t` asks whether `t` holds something at `key`: in Lua a
507
+ key whose value is nil is a key that is not there, so it is `t.key ~= nil`.
508
+ The key is a string or a number and `t` a table. It narrows as TypeScript's
509
+ does: where it holds, `t` is one of the union members that can have `key`, and
510
+ `t.key` is not nil; where it does not, `t` is none of the members that must.
511
+
512
+ **`instanceof`** — `v instanceof Dog` is true when `v` was built by `Dog` or
513
+ by a class extending it. It walks the links every instance has: `v.ClassObject`,
514
+ then each `.ParentClass` up the chain. It narrows `v` to `Dog`, and only a
515
+ class written in tilua can stand on its right — a `declare class` is the
516
+ host's, and Roblox's answer `IsA` instead.
517
+
518
+ **Accessors in an object literal** — `{ get full() { ... }, set full(v) { ...
519
+ } }` reads and writes `full` through functions, with the object as `this`. Lua
520
+ has no such thing, so the object gets a metatable that runs them; a name with a
521
+ getter and no setter is read-only, and assigning it is an error at runtime as
522
+ well as in the types.
523
+
393
524
  **Classes** — types are structural, except for classes. A definitions file
394
525
  declares one with `declare class`, and it is nominal, as Roblox's classes are:
395
526
 
@@ -522,7 +653,7 @@ class Square extends Shape {
522
653
  instances' metatable, so `function __add(other: Vec): Vec` in a class is the
523
654
  `+` of its instances — and the type checker reads it the same way: `a + b`
524
655
  between two `Vec`s is a `Vec`. `__sub`, `__mul`, `__div`, `__idiv`, `__mod`,
525
- `__pow`, `__unm`, `__concat`, `__len` (`#v`), `__eq`, `__lt` and `__le` (`<`,
656
+ `__pow`, `__unm`, `__concat`, `__len` (`v.length`), `__eq`, `__lt` and `__le` (`<`,
526
657
  `>`, `<=`, `>=`), `__call` (calling an instance), `__iter` (`for a, b in v`)
527
658
  and `__tostring` all work this way, and a class extending another inherits
528
659
  them. Each is checked: it takes the operands Luau hands it, returns what Luau
@@ -708,14 +839,24 @@ destructuring instead.
708
839
  ```luau
709
840
  join("-", ...names) -- every name
710
841
  join("-", ...names, "z") -- and one more after them
711
- add3(...nums) -- however many `nums` turns out to hold
842
+ add3(...trio) -- `trio: [number, number, number]`: exactly three
712
843
  const both = [...names, "z"]
713
844
  ```
714
845
 
715
- What the array holds is checked against what it fills. How many it holds is
716
- not known, so nothing is said about the count — unless it is a tuple, which
717
- holds a known value at each position and is checked one by one. Spreading
718
- something that is not a list is reported.
846
+ What the array holds is checked against what it fills. How many an array
847
+ holds is not known, so, as in TypeScript, it can only fill a rest parameter —
848
+ `add3(...nums)` with `nums: number[]` is an error, and so is `h(...nums)` for
849
+ an `h(a: number, ...more: number[])`, whose `a` it would have to fill. A
850
+ tuple holds a known value at each position: it fills exactly that many
851
+ parameters, checked one by one and counted, several tuples together too.
852
+ Spreading something that is not a list is reported, and so is spreading a
853
+ list that may be nil — write `...(xs ?? [])`.
854
+
855
+ In an object literal, `...source` copies what `source` has: over a union, one
856
+ object per member; over a value that may be nil, every member optional; over
857
+ a class instance, its fields — its methods live on the class table, which a
858
+ copy does not reach. A copy is a new table, so nothing in it is read-only.
859
+ `const [first, ...rest] = tuple` leaves `rest` a tuple of what is left.
719
860
 
720
861
  **Branded types** — nothing in the type model is about branding; an
721
862
  intersection already means it. `string & { __brand }` is assignable to
@@ -732,7 +873,7 @@ findUser(id) -- ok
732
873
  findUser("raw") -- '"raw"' is not assignable to 'UserId'
733
874
  findUser(postId) -- 'PostId' is not assignable to 'UserId'
734
875
 
735
- #id -- still a string: 5
876
+ id.length -- still a string: 5
736
877
  id:upper() -- and its methods, giving a plain string
737
878
  ```
738
879
 
@@ -771,6 +912,26 @@ parameter reads `Extract<Rows, { Page: P }>["Skills"][number]`. A type that
771
912
  waits on a type parameter — a conditional, an index, `T[K]` — is worked out
772
913
  where that parameter is.
773
914
 
915
+ **Functions compare as under `strictFunctionTypes`.** A function fits a
916
+ function type when it takes whatever that type's callers pass — its parameters
917
+ are contravariant — and needs no more arguments than they hand it: `(x: Part)
918
+ => nil` is not a `(x: Instance) => nil`, which may be called with any
919
+ instance. A method — a function taking its receiver first, `self` or `this`
920
+ — is compared both ways, as TypeScript compares methods, so an override may
921
+ narrow what it takes.
922
+
923
+ **Every way through returns.** A function that declares a return type which
924
+ does not admit `nil` has to return on every way to its end: `Not every path
925
+ returns a value` otherwise. A call that is `never` (`error(...)`) ends a way,
926
+ and so does `while (true)` with no `break` of its own.
927
+
928
+ **An `if` chain can be exhaustive.** tilua has no `switch`; an `if` /
929
+ `elseif` chain whose tests leave no value for an `else` — every member of
930
+ `x: "a" | "b"` tested — has no way past it but its branches. A function whose
931
+ chain returns in every branch needs no `return` after it, and after it `x` is
932
+ `never`, which is how `const unreachable: never = x` checks that a new
933
+ member was not forgotten.
934
+
774
935
  **Trailing commas** are allowed wherever TypeScript allows them: parameter
775
936
  lists, call arguments, generic parameters and type arguments, tables, arrays,
776
937
  tuples, imports and exports.
@@ -807,18 +968,79 @@ type says so — it is `any`, and `any` turns off every check made of it.
807
968
  **Types** — unions, intersections, tuples `[A, B]` (with a rest, `[A,
808
969
  ...B[]]`), `keyof`, `T[K]`, conditional types with
809
970
  `infer`, mapped types with `as` remapping, template literal types
810
- (`` `on${Event}` ``), and set difference `A - B`. The utility types
971
+ (`` `on${Event}` ``), and `Exclude<A, B>`. The utility types
811
972
  (`Partial`, `Pick`, `Omit`, `ReturnType`, `Parameters`, `Exclude`, …) are
812
973
  built in, and written in tilua on top of those rather than special-cased in
813
974
  the analyzer. A type library or a file may declare one again; the later
814
975
  declaration wins.
815
976
 
977
+ Type-level programs work as they do in TypeScript. A tuple may spread anywhere
978
+ (`[...A, ...B]`, `[infer H, ...infer R]`) and name its elements
979
+ (`[x: number, y?: number]`) — an element marked `?` may be left out, so
980
+ `[number, string?]` takes `[1]` and its `length` is `1 | 2`, and
981
+ `Parameters<(a: number, b?: string) => nil>` is `[a: number, b?: string]`; a
982
+ list of any length may stand before the elements written after it
983
+ (`[...unknown[], infer L]`); `T["length"]` counts a tuple, and `keyof` a list is
984
+ its positions and its `length`, `number | "length"` (`keyof string[]` is the
985
+ list's keys, `(keyof T)[]` a list of keys, as TypeScript reads them); an alias may
986
+ recurse (`type Reverse<T> = T extends [infer H, ...infer R] ? [...Reverse<R>,
987
+ H] : []`); a template literal pattern takes a string apart (`` S extends
988
+ `${infer A}.${infer B}` ``), and `infer N extends number` reads `"42"` as
989
+ `42`. `object` is anything that is not a primitive. One difference: a tuple's
990
+ positions count from 1, as Lua's do, so the first element of `T` is `T[1]`.
991
+ A recursion that never ends stops after 100 levels and gives `any`.
992
+
993
+ **What `${...}` may hold** — a template string writes each value with
994
+ `tostring`, so it takes what reads as text: a string, a number, a boolean,
995
+ `nil`, and a value that says how to print itself — a class with `__tostring`,
996
+ or one the host made (a Roblox `Instance`, a `Vector3`). A table, a list, a
997
+ function or a class instance without `__tostring` would print as its address
998
+ (`table: 0x...`), and is an error. A template literal *type* holds a string,
999
+ a number, a boolean or `nil` in each placeholder, as TypeScript's does:
1000
+ `` `a${number[]}` `` is an error, and so is a `T extends object` there.
1001
+
1002
+ A generic function may take and give variadic tuples: `<T extends unknown[]>(xs:
1003
+ [...T]): T` reads `[1, "a"]` as `[number, string]`, `(...args: [...T, string])`
1004
+ takes the last argument apart from the others, and `(fn: (...args: [...A,
1005
+ ...B]) => R, ...a: A): (...b: B) => R` binds the first arguments of `fn`.
1006
+
1007
+ `Exclude<T, U>` — what of `T` is not a `U` — is the analyzer's own, and unlike
1008
+ TypeScript's it is kept where TypeScript's would forget it: `Exclude<unknown,
1009
+ nil>` and `Exclude<any, nil>` stay, as a value known not to be `nil`, and so
1010
+ does `Exclude<string, "a">`, a string that is not `"a"` — of which `if (s ==
1011
+ "a")` is reported as a test that can never pass. Over a union it drops the
1012
+ members it takes whole (`Exclude<"a" | "b", "b">` is `"a"`), and `boolean` is
1013
+ the union `true | false`.
1014
+ tilua has no `A - B` in types; `Exclude` is the one way to write it.
1015
+
816
1016
  A call may write its type arguments out — `find<Folder>("Remotes")`,
817
1017
  `inst:WaitForChild<Folder>("Remotes")` — and a type parameter may have a
818
1018
  default (`<T = Instance>`) for the calls that do not. `a < b > (c)` is still
819
1019
  three operators: only a call after the `>` makes it type arguments.
820
1020
 
821
- `<const T>` infers an argument at its narrowest, as in TypeScript 5.
1021
+ `<const T>` infers an argument at its narrowest, as in TypeScript 5. Without it
1022
+ a literal is still kept where the function gives `T` itself back —
1023
+ `identity("x")` is `"x"`, and a `let` it is given to widens it to `string` —
1024
+ and a `K extends keyof T`, or a `T extends string`, keeps the key or the text
1025
+ written. Literals of one primitive read for one parameter are either:
1026
+ `pair(1, 2)` is `1 | 2`. `as const` makes its lists read-only:
1027
+ `[1, 2] as const` is a `readonly [1, 2]`. `ReturnType` of an overloaded
1028
+ function is its last signature's, as in TypeScript.
1029
+
1030
+ `NoInfer<T>` is `T`, except that a call does not work `T` out from an
1031
+ argument written there: `function pick<T>(a: T, fallback: NoInfer<T>): T`
1032
+ takes `T` from `a` alone, and checks `fallback` against it.
1033
+
1034
+ A type alias or an interface may say how it compares by a parameter:
1035
+ `type Getter<out T>` as `T` does, `type Setter<in T>` the other way round,
1036
+ `<in out T>` only by the same `T`. It is checked against the body —
1037
+ `type Getter<in T> = { get: () => T }` is an error — and a function's or a
1038
+ class's parameters take none.
1039
+
1040
+ `new (name: string) => Dog` is the type of a class table that builds a `Dog`:
1041
+ tilua builds with `Dog.new(name)`, so it is `{ new: (name: string) => Dog }`.
1042
+ `InstanceType<typeof Dog>` and `ConstructorParameters<typeof Dog>` read it
1043
+ back, as TypeScript's do.
822
1044
 
823
1045
  `typeof x` in a type is TypeScript's type query — the type of a value
824
1046
  (`typeof config`, `typeof config.volume`, `ReturnType<typeof f>`). Luau's
@@ -827,6 +1049,14 @@ three operators: only a call after the `>` makes it type arguments.
827
1049
  runs.
828
1050
 
829
1051
  **Modules** — `import` / `export`, export lists, re-exports and `export *`.
1052
+ `export type { A }` (and `export type { A } from "./m"`) exports types and
1053
+ nothing else; naming a value there is an error.
1054
+
1055
+ **What TypeScript has and tilua does not** says what to write instead, rather
1056
+ than reading as something else: `enum`, `namespace`, `try` / `catch`,
1057
+ `switch`, `declare module` and `declare global` are each reported with the
1058
+ tilua spelling. (A name followed by `{` is otherwise a call with a table
1059
+ argument, so `enum Color { ... }` would have meant `enum(Color { ... })`.)
830
1060
 
831
1061
  **`satisfies`** — checks a value against a type without giving it that type,
832
1062
  as in TypeScript 4.9:
@@ -888,11 +1118,9 @@ analyzeTypes(program, scopes, {
888
1118
 
889
1119
  ## Known limitations
890
1120
 
891
- - `export * as ns from` and namespace imports (`import * as ns`) are not
892
- supported.
893
- - `setmetatable` and metatables are not modelled.
894
- - Accessing a property a type does not have yields `unknown` rather than an
895
- error; assigning to a `readonly` property is not reported.
1121
+ - `export * as ns from` is not supported.
1122
+ - `setmetatable` is not modelled: a table given a metatable at runtime keeps
1123
+ the type it had.
896
1124
  - A sourcemap child whose name is not an identifier (`"My Part"`) is not typed.
897
1125
 
898
1126
  ## Development