@tilua/parser 4.0.0 → 5.0.1

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,14 @@ 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)[]`). `keys`, `values` and `entries` answer
357
+ arrays rather than JavaScript's iterators — `for (const [i, v] in
358
+ xs:entries())` — counting from 1. The ones that only read take a read-only
359
+ list too (`readonly T[]`, what `as const` makes), as TypeScript's
360
+ `ReadonlyArray` does; the ones that change it do not. A table's are `keys`, `values` and `entries`, which answer a tuple
298
361
  in the order the table's type wrote its members, not `string[]` as
299
362
  JavaScript's `Object.keys` does; the analyzer supplies that order as
300
363
  `ObjectKeys<T>`, `ObjectValues<T>` and `ObjectEntries<T>`. A member of a
@@ -302,7 +365,7 @@ value's own with the same name is what a call reaches, and a class instance,
302
365
  which has a metatable of its own, has none of them.
303
366
 
304
367
  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)`);
368
+ call into its own runtime (`names.filter(f)` becomes `array.filter(names, f)`);
306
369
  a string's Lua methods stay plain method calls.
307
370
 
308
371
  A library adds to a metatable by declaring the same target again, and a
@@ -358,8 +421,8 @@ such as `print(x)`, and `globalValue` for a global read as a value, such as
358
421
  hook is asked about it. A runtime can read `__LINES__`, the bundle's line map
359
422
  (`nil` outside a bundle), to turn a line Luau reports back into a place in the
360
423
  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.
424
+ writes it down as an array for `typeof`. The compiler's own lowering of the
425
+ standard library — `console:log`, `error`, `pcall` — is built on these hooks.
363
426
 
364
427
  **A `(` that starts a line** continues the statement above it, as in Lua and
365
428
  in JavaScript — `const v = map[key]` followed by `("A"):upper()` is one
@@ -368,6 +431,53 @@ write `;` before the `(` when a new statement was meant.
368
431
 
369
432
  **Object types** — `{ name: T, name?: T, [K]: V }`, and a name that is not an
370
433
  identifier is quoted, as in the literal: `{ "Respawn After Kill": boolean }`.
434
+ An index signature may name its key as TypeScript does, `[key: string]: V`, and
435
+ its key may be a template literal: `` { [`on${string}`]: Handler } `` takes every
436
+ `onX`, and an object literal with any other key is excess. A string or a list
437
+ fits a shape that names what it answers to: `"abc"` is a `{ length: number }`.
438
+ Members are separated by `,`, `;` or a line break, and may be written the
439
+ other ways TypeScript writes them:
440
+
441
+ ```luau
442
+ type Counter = {
443
+ readonly id: number
444
+ step(by: number): this -- a method: (self: this, by: number) => this
445
+ reset?(): nil -- an optional one
446
+ get total(): number -- read-only, unless a `set` is written too
447
+ set label(value: string)
448
+ (n: number): string -- calling the value; several are overloads
449
+ new (seed: number): Counter -- what its `new` makes: { new: (seed: number) => Counter }
450
+ }
451
+ ```
452
+
453
+ A method is called with `:`, as a class's methods are: its first parameter is
454
+ the receiver, typed `this`, so `counter:step(1)` hands `counter` over and
455
+ `counter.step(1)` is the missing argument it is. A signature with no return
456
+ type returns `nil`. Calling the value and having members too is the functions
457
+ and the members together — Lua builds such a value with a `__call` metatable.
458
+
459
+ **Interfaces** — `interface Name<T> extends A, B<T> { ... }`, with the members
460
+ an object type takes. It is a type alias for the bases and the members
461
+ together, with what TypeScript adds: two interfaces of one name are one, their
462
+ members merged (a method written in each is an overload set), and a member
463
+ that does not fit the one it replaces in a base is reported. `export
464
+ interface` exports it, as `export type` does.
465
+
466
+ ```luau
467
+ interface Named { name: string }
468
+ interface Greeter extends Named {
469
+ greet(other: Named): string
470
+ }
471
+ class Person implements Greeter {
472
+ name = "Ada"
473
+ function greet(other: Named): string { return `hi ${other.name}` }
474
+ }
475
+ ```
476
+
477
+ **`this` in a type** — TypeScript's polymorphic `this`: the value a member is
478
+ read from. A method that returns `this` returns whatever it was called on, so
479
+ `Builder.new():add(1):done()` keeps the subclass's members through the chain.
480
+ Inside the class it is the instance.
371
481
 
372
482
  **Optionality** — there is no `T?` shorthand. `?` in type position always
373
483
  belongs to a conditional type, and in expression position to a ternary or an
@@ -390,6 +500,29 @@ ternary. Parentheses end a chain. A chain cannot be assigned to (`a?.b = 1` is
390
500
  an error). A chain that got through narrows what it tested: inside
391
501
  `if (part?.Parent)`, and `if (part?.Name == "Door")`, `part` is not nil.
392
502
 
503
+ **`??`** — `a ?? b` is `a`, or `b` where `a` is nil; `b` is read only then.
504
+ Unlike `a or b` a `false` stays, which is what a `boolean | nil` wants:
505
+ `settings.enabled ?? true`. As in TypeScript it does not mix with `and` or
506
+ `or` without parentheses.
507
+
508
+ **`in`** — `"key" in t` asks whether `t` holds something at `key`: in Lua a
509
+ key whose value is nil is a key that is not there, so it is `t.key ~= nil`.
510
+ The key is a string or a number and `t` a table. It narrows as TypeScript's
511
+ does: where it holds, `t` is one of the union members that can have `key`, and
512
+ `t.key` is not nil; where it does not, `t` is none of the members that must.
513
+
514
+ **`instanceof`** — `v instanceof Dog` is true when `v` was built by `Dog` or
515
+ by a class extending it. It walks the links every instance has: `v.ClassObject`,
516
+ then each `.ParentClass` up the chain. It narrows `v` to `Dog`, and only a
517
+ class written in tilua can stand on its right — a `declare class` is the
518
+ host's, and Roblox's answer `IsA` instead.
519
+
520
+ **Accessors in an object literal** — `{ get full() { ... }, set full(v) { ...
521
+ } }` reads and writes `full` through functions, with the object as `this`. Lua
522
+ has no such thing, so the object gets a metatable that runs them; a name with a
523
+ getter and no setter is read-only, and assigning it is an error at runtime as
524
+ well as in the types.
525
+
393
526
  **Classes** — types are structural, except for classes. A definitions file
394
527
  declares one with `declare class`, and it is nominal, as Roblox's classes are:
395
528
 
@@ -522,7 +655,7 @@ class Square extends Shape {
522
655
  instances' metatable, so `function __add(other: Vec): Vec` in a class is the
523
656
  `+` of its instances — and the type checker reads it the same way: `a + b`
524
657
  between two `Vec`s is a `Vec`. `__sub`, `__mul`, `__div`, `__idiv`, `__mod`,
525
- `__pow`, `__unm`, `__concat`, `__len` (`#v`), `__eq`, `__lt` and `__le` (`<`,
658
+ `__pow`, `__unm`, `__concat`, `__len` (`v.length`), `__eq`, `__lt` and `__le` (`<`,
526
659
  `>`, `<=`, `>=`), `__call` (calling an instance), `__iter` (`for a, b in v`)
527
660
  and `__tostring` all work this way, and a class extending another inherits
528
661
  them. Each is checked: it takes the operands Luau hands it, returns what Luau
@@ -562,7 +695,11 @@ Dog.ParentClass == Animal -- a class names the one it extends
562
695
  Animal.ParentClass == nil -- and a root class extends nothing
563
696
  ```
564
697
 
565
- Both live on the class table, so an instance carries neither.
698
+ Both live on the class table, so an instance carries neither. So does its
699
+ name, as a JavaScript class's `name`: `Dog.name` is `"Dog"`, and a class
700
+ written as a value takes the name of what holds it (`const Counter = class
701
+ { ... }` is `"Counter"`). A static, a method or an accessor cannot be called
702
+ `name`; an instance field can, and lives on the instance.
566
703
 
567
704
  **Generic classes** — `class Box<T> { ... }`. The name is then a generic type,
568
705
  and `Box<number>` and `Box<string>` are both `Box` but neither is the other:
@@ -708,14 +845,24 @@ destructuring instead.
708
845
  ```luau
709
846
  join("-", ...names) -- every name
710
847
  join("-", ...names, "z") -- and one more after them
711
- add3(...nums) -- however many `nums` turns out to hold
848
+ add3(...trio) -- `trio: [number, number, number]`: exactly three
712
849
  const both = [...names, "z"]
713
850
  ```
714
851
 
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.
852
+ What the array holds is checked against what it fills. How many an array
853
+ holds is not known, so, as in TypeScript, it can only fill a rest parameter —
854
+ `add3(...nums)` with `nums: number[]` is an error, and so is `h(...nums)` for
855
+ an `h(a: number, ...more: number[])`, whose `a` it would have to fill. A
856
+ tuple holds a known value at each position: it fills exactly that many
857
+ parameters, checked one by one and counted, several tuples together too.
858
+ Spreading something that is not a list is reported, and so is spreading a
859
+ list that may be nil — write `...(xs ?? [])`.
860
+
861
+ In an object literal, `...source` copies what `source` has: over a union, one
862
+ object per member; over a value that may be nil, every member optional; over
863
+ a class instance, its fields — its methods live on the class table, which a
864
+ copy does not reach. A copy is a new table, so nothing in it is read-only.
865
+ `const [first, ...rest] = tuple` leaves `rest` a tuple of what is left.
719
866
 
720
867
  **Branded types** — nothing in the type model is about branding; an
721
868
  intersection already means it. `string & { __brand }` is assignable to
@@ -732,7 +879,7 @@ findUser(id) -- ok
732
879
  findUser("raw") -- '"raw"' is not assignable to 'UserId'
733
880
  findUser(postId) -- 'PostId' is not assignable to 'UserId'
734
881
 
735
- #id -- still a string: 5
882
+ id.length -- still a string: 5
736
883
  id:upper() -- and its methods, giving a plain string
737
884
  ```
738
885
 
@@ -771,6 +918,26 @@ parameter reads `Extract<Rows, { Page: P }>["Skills"][number]`. A type that
771
918
  waits on a type parameter — a conditional, an index, `T[K]` — is worked out
772
919
  where that parameter is.
773
920
 
921
+ **Functions compare as under `strictFunctionTypes`.** A function fits a
922
+ function type when it takes whatever that type's callers pass — its parameters
923
+ are contravariant — and needs no more arguments than they hand it: `(x: Part)
924
+ => nil` is not a `(x: Instance) => nil`, which may be called with any
925
+ instance. A method — a function taking its receiver first, `self` or `this`
926
+ — is compared both ways, as TypeScript compares methods, so an override may
927
+ narrow what it takes.
928
+
929
+ **Every way through returns.** A function that declares a return type which
930
+ does not admit `nil` has to return on every way to its end: `Not every path
931
+ returns a value` otherwise. A call that is `never` (`error(...)`) ends a way,
932
+ and so does `while (true)` with no `break` of its own.
933
+
934
+ **An `if` chain can be exhaustive.** tilua has no `switch`; an `if` /
935
+ `elseif` chain whose tests leave no value for an `else` — every member of
936
+ `x: "a" | "b"` tested — has no way past it but its branches. A function whose
937
+ chain returns in every branch needs no `return` after it, and after it `x` is
938
+ `never`, which is how `const unreachable: never = x` checks that a new
939
+ member was not forgotten.
940
+
774
941
  **Trailing commas** are allowed wherever TypeScript allows them: parameter
775
942
  lists, call arguments, generic parameters and type arguments, tables, arrays,
776
943
  tuples, imports and exports.
@@ -807,18 +974,79 @@ type says so — it is `any`, and `any` turns off every check made of it.
807
974
  **Types** — unions, intersections, tuples `[A, B]` (with a rest, `[A,
808
975
  ...B[]]`), `keyof`, `T[K]`, conditional types with
809
976
  `infer`, mapped types with `as` remapping, template literal types
810
- (`` `on${Event}` ``), and set difference `A - B`. The utility types
977
+ (`` `on${Event}` ``), and `Exclude<A, B>`. The utility types
811
978
  (`Partial`, `Pick`, `Omit`, `ReturnType`, `Parameters`, `Exclude`, …) are
812
979
  built in, and written in tilua on top of those rather than special-cased in
813
980
  the analyzer. A type library or a file may declare one again; the later
814
981
  declaration wins.
815
982
 
983
+ Type-level programs work as they do in TypeScript. A tuple may spread anywhere
984
+ (`[...A, ...B]`, `[infer H, ...infer R]`) and name its elements
985
+ (`[x: number, y?: number]`) — an element marked `?` may be left out, so
986
+ `[number, string?]` takes `[1]` and its `length` is `1 | 2`, and
987
+ `Parameters<(a: number, b?: string) => nil>` is `[a: number, b?: string]`; a
988
+ list of any length may stand before the elements written after it
989
+ (`[...unknown[], infer L]`); `T["length"]` counts a tuple, and `keyof` a list is
990
+ its positions and its `length`, `number | "length"` (`keyof string[]` is the
991
+ list's keys, `(keyof T)[]` a list of keys, as TypeScript reads them); an alias may
992
+ recurse (`type Reverse<T> = T extends [infer H, ...infer R] ? [...Reverse<R>,
993
+ H] : []`); a template literal pattern takes a string apart (`` S extends
994
+ `${infer A}.${infer B}` ``), and `infer N extends number` reads `"42"` as
995
+ `42`. `object` is anything that is not a primitive. One difference: a tuple's
996
+ positions count from 1, as Lua's do, so the first element of `T` is `T[1]`.
997
+ A recursion that never ends stops after 100 levels and gives `any`.
998
+
999
+ **What `${...}` may hold** — a template string writes each value with
1000
+ `tostring`, so it takes what reads as text: a string, a number, a boolean,
1001
+ `nil`, and a value that says how to print itself — a class with `__tostring`,
1002
+ or one the host made (a Roblox `Instance`, a `Vector3`). A table, a list, a
1003
+ function or a class instance without `__tostring` would print as its address
1004
+ (`table: 0x...`), and is an error. A template literal *type* holds a string,
1005
+ a number, a boolean or `nil` in each placeholder, as TypeScript's does:
1006
+ `` `a${number[]}` `` is an error, and so is a `T extends object` there.
1007
+
1008
+ A generic function may take and give variadic tuples: `<T extends unknown[]>(xs:
1009
+ [...T]): T` reads `[1, "a"]` as `[number, string]`, `(...args: [...T, string])`
1010
+ takes the last argument apart from the others, and `(fn: (...args: [...A,
1011
+ ...B]) => R, ...a: A): (...b: B) => R` binds the first arguments of `fn`.
1012
+
1013
+ `Exclude<T, U>` — what of `T` is not a `U` — is the analyzer's own, and unlike
1014
+ TypeScript's it is kept where TypeScript's would forget it: `Exclude<unknown,
1015
+ nil>` and `Exclude<any, nil>` stay, as a value known not to be `nil`, and so
1016
+ does `Exclude<string, "a">`, a string that is not `"a"` — of which `if (s ==
1017
+ "a")` is reported as a test that can never pass. Over a union it drops the
1018
+ members it takes whole (`Exclude<"a" | "b", "b">` is `"a"`), and `boolean` is
1019
+ the union `true | false`.
1020
+ tilua has no `A - B` in types; `Exclude` is the one way to write it.
1021
+
816
1022
  A call may write its type arguments out — `find<Folder>("Remotes")`,
817
1023
  `inst:WaitForChild<Folder>("Remotes")` — and a type parameter may have a
818
1024
  default (`<T = Instance>`) for the calls that do not. `a < b > (c)` is still
819
1025
  three operators: only a call after the `>` makes it type arguments.
820
1026
 
821
- `<const T>` infers an argument at its narrowest, as in TypeScript 5.
1027
+ `<const T>` infers an argument at its narrowest, as in TypeScript 5. Without it
1028
+ a literal is still kept where the function gives `T` itself back —
1029
+ `identity("x")` is `"x"`, and a `let` it is given to widens it to `string` —
1030
+ and a `K extends keyof T`, or a `T extends string`, keeps the key or the text
1031
+ written. Literals of one primitive read for one parameter are either:
1032
+ `pair(1, 2)` is `1 | 2`. `as const` makes its lists read-only:
1033
+ `[1, 2] as const` is a `readonly [1, 2]`. `ReturnType` of an overloaded
1034
+ function is its last signature's, as in TypeScript.
1035
+
1036
+ `NoInfer<T>` is `T`, except that a call does not work `T` out from an
1037
+ argument written there: `function pick<T>(a: T, fallback: NoInfer<T>): T`
1038
+ takes `T` from `a` alone, and checks `fallback` against it.
1039
+
1040
+ A type alias or an interface may say how it compares by a parameter:
1041
+ `type Getter<out T>` as `T` does, `type Setter<in T>` the other way round,
1042
+ `<in out T>` only by the same `T`. It is checked against the body —
1043
+ `type Getter<in T> = { get: () => T }` is an error — and a function's or a
1044
+ class's parameters take none.
1045
+
1046
+ `new (name: string) => Dog` is the type of a class table that builds a `Dog`:
1047
+ tilua builds with `Dog.new(name)`, so it is `{ new: (name: string) => Dog }`.
1048
+ `InstanceType<typeof Dog>` and `ConstructorParameters<typeof Dog>` read it
1049
+ back, as TypeScript's do.
822
1050
 
823
1051
  `typeof x` in a type is TypeScript's type query — the type of a value
824
1052
  (`typeof config`, `typeof config.volume`, `ReturnType<typeof f>`). Luau's
@@ -827,6 +1055,14 @@ three operators: only a call after the `>` makes it type arguments.
827
1055
  runs.
828
1056
 
829
1057
  **Modules** — `import` / `export`, export lists, re-exports and `export *`.
1058
+ `export type { A }` (and `export type { A } from "./m"`) exports types and
1059
+ nothing else; naming a value there is an error.
1060
+
1061
+ **What TypeScript has and tilua does not** says what to write instead, rather
1062
+ than reading as something else: `enum`, `namespace`, `try` / `catch`,
1063
+ `switch`, `declare module` and `declare global` are each reported with the
1064
+ tilua spelling. (A name followed by `{` is otherwise a call with a table
1065
+ argument, so `enum Color { ... }` would have meant `enum(Color { ... })`.)
830
1066
 
831
1067
  **`satisfies`** — checks a value against a type without giving it that type,
832
1068
  as in TypeScript 4.9:
@@ -888,11 +1124,9 @@ analyzeTypes(program, scopes, {
888
1124
 
889
1125
  ## Known limitations
890
1126
 
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.
1127
+ - `export * as ns from` is not supported.
1128
+ - `setmetatable` is not modelled: a table given a metatable at runtime keeps
1129
+ the type it had.
896
1130
  - A sourcemap child whose name is not an identifier (`"My Part"`) is not typed.
897
1131
 
898
1132
  ## Development