gofront 0.0.8 → 1.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.
Files changed (51) hide show
  1. package/README.md +88 -12
  2. package/package.json +8 -4
  3. package/src/codegen/expressions.js +520 -1717
  4. package/src/{codegen.js → codegen/index.js} +155 -184
  5. package/src/codegen/runtime.js +151 -0
  6. package/src/codegen/statements.js +305 -296
  7. package/src/codegen/stdlib/builder.js +36 -0
  8. package/src/codegen/stdlib/bytes.js +62 -0
  9. package/src/codegen/stdlib/errors.js +17 -0
  10. package/src/codegen/stdlib/fmt.js +101 -0
  11. package/src/codegen/stdlib/gom.js +152 -0
  12. package/src/codegen/stdlib/html.js +17 -0
  13. package/src/codegen/stdlib/index.js +95 -0
  14. package/src/codegen/stdlib/io.js +33 -0
  15. package/src/codegen/stdlib/maps.js +42 -0
  16. package/src/codegen/stdlib/math.js +53 -0
  17. package/src/codegen/stdlib/os.js +10 -0
  18. package/src/codegen/stdlib/path.js +31 -0
  19. package/src/codegen/stdlib/rand.js +24 -0
  20. package/src/codegen/stdlib/regexp.js +51 -0
  21. package/src/codegen/stdlib/slices.js +48 -0
  22. package/src/codegen/stdlib/sort.js +28 -0
  23. package/src/codegen/stdlib/strconv.js +30 -0
  24. package/src/codegen/stdlib/strings.js +83 -0
  25. package/src/codegen/stdlib/time.js +54 -0
  26. package/src/codegen/stdlib/unicode.js +22 -0
  27. package/src/codegen/stdlib/utf8.js +23 -0
  28. package/src/codegen/templ.js +281 -0
  29. package/src/compiler.js +102 -62
  30. package/src/dts-parser.js +355 -371
  31. package/src/index.js +22 -54
  32. package/src/lexer.js +200 -286
  33. package/src/minifier.js +305 -318
  34. package/src/parser/expressions.js +54 -36
  35. package/src/{parser.js → parser/index.js} +12 -5
  36. package/src/parser/statements.js +29 -35
  37. package/src/parser/types.js +31 -29
  38. package/src/templ-lexer.js +737 -0
  39. package/src/templ-parser.js +235 -0
  40. package/src/tokens.js +109 -0
  41. package/src/typechecker/assignability.js +258 -0
  42. package/src/typechecker/expressions.js +559 -549
  43. package/src/typechecker/index.js +555 -0
  44. package/src/typechecker/resolve.js +421 -0
  45. package/src/typechecker/statements.js +267 -280
  46. package/src/typechecker/stdlib/core.js +592 -0
  47. package/src/typechecker/stdlib/extended.js +332 -0
  48. package/src/typechecker/stdlib.js +9 -1060
  49. package/src/typechecker/termination.js +83 -0
  50. package/src/typechecker/types.js +6 -3
  51. package/src/typechecker.js +0 -1271
@@ -0,0 +1,555 @@
1
+ // Type checker: walks the AST, resolves types for all expressions,
2
+ // and reports type errors at compile time.
3
+ //
4
+ // Split into sub-modules under typechecker/:
5
+ // types.js — shared type constants, predicates, Scope
6
+ // stdlib.js — browser globals + all built-in package registrations
7
+ // statements.js — checkBlock, checkStmt
8
+ // expressions.js — checkExpr, checkCall, checkBuiltin, checkCompositeLit
9
+ // termination.js — _isTerminating* family
10
+ // resolve.js — resolveTypeNode, fieldType, generics
11
+ // assignability.js — assertAssignable, binaryResultType, implements
12
+
13
+ import { assignabilityMethods } from "./assignability.js";
14
+ import { expressionCheckMethods } from "./expressions.js";
15
+ import { resolveMethods } from "./resolve.js";
16
+ import { statementCheckMethods } from "./statements.js";
17
+ import { setupGlobals } from "./stdlib.js";
18
+ import { terminationMethods } from "./termination.js";
19
+ import {
20
+ ANY,
21
+ defaultType,
22
+ ERROR,
23
+ isVoid,
24
+ Scope,
25
+ TypeCheckError,
26
+ typeStr,
27
+ VOID,
28
+ } from "./types.js";
29
+
30
+ // Re-export for consumers that import from typechecker.js
31
+ export { TypeCheckError, typeStr };
32
+
33
+ export class TypeChecker {
34
+ constructor() {
35
+ this.types = new Map(); // named types
36
+ this.globals = new Scope();
37
+ this.errors = [];
38
+ this._currentFile = null; // filename of file currently being checked
39
+ this._currentSource = null;
40
+ this._loopDepth = 0; // for break/continue validation
41
+ this._switchDepth = 0; // for break/fallthrough validation
42
+ this._typeSwitchDepth = 0; // for rejecting fallthrough in type switch
43
+ this._deferCount = 0; // tracks defer usage in current function body
44
+ this._imports = []; // tracked imports for unused-import detection
45
+ this._setupGlobals();
46
+ // Register error as a named type (interface)
47
+ this.types.set("error", ERROR);
48
+ }
49
+
50
+ _setupGlobals() {
51
+ setupGlobals(this.globals, this.types);
52
+ }
53
+
54
+ addDefinitions(types, values) {
55
+ for (const [name, type] of types) {
56
+ this.types.set(name, type);
57
+ }
58
+ for (const [name, type] of values) {
59
+ this.globals.define(name, type);
60
+ }
61
+ }
62
+
63
+ // Add an imported GoFront package as a qualified namespace.
64
+ // e.g. addPackageNamespace('utils', symbolsMap, typesMap)
65
+ // lets callers type-check `utils.Foo` via SelectorExpr.
66
+ addPackageNamespace(pkgName, symbols, types) {
67
+ const members = {};
68
+ for (const [name, type] of symbols) members[name] = type;
69
+ // _gofront: true marks this as a GoFront package — exported identifier rules apply
70
+ this.globals.define(pkgName, {
71
+ kind: "namespace",
72
+ name: pkgName,
73
+ members,
74
+ _gofront: true,
75
+ });
76
+ for (const [name, type] of types) {
77
+ this.types.set(name, type);
78
+ this.types.set(`${pkgName}.${name}`, type);
79
+ }
80
+ }
81
+
82
+ // Register an import for unused-import detection.
83
+ // `name` is the package name or alias used in code.
84
+ // `node` carries _line for error reporting.
85
+ // `filename` / `source` identify the file containing the import.
86
+ trackImport(name, node, filename, source) {
87
+ this._imports.push({ name, node, filename, source });
88
+ }
89
+
90
+ // Report any tracked imports whose package name was never referenced.
91
+ reportUnusedImports() {
92
+ for (const { name, node, filename, source } of this._imports) {
93
+ if (!this.globals._used.has(name)) {
94
+ const saved = [this._currentFile, this._currentSource];
95
+ this._currentFile = filename;
96
+ this._currentSource = source;
97
+ this.err(`'${name}' imported and not used`, node);
98
+ [this._currentFile, this._currentSource] = saved;
99
+ }
100
+ }
101
+ }
102
+
103
+ // Return a snapshot of all user-defined globals (excludes built-ins).
104
+ // Used by the compiler to expose a package's exports to importers.
105
+ getExportedSymbols() {
106
+ const out = new Map();
107
+ for (const [name, type] of this.globals.symbols) {
108
+ if (type?.kind === "builtin") continue; // skip built-ins
109
+ if (type === ANY && !name[0].match(/[A-Z]/)) continue; // skip browser globals
110
+ out.set(name, type);
111
+ }
112
+ return out;
113
+ }
114
+
115
+ getExportedTypes() {
116
+ return new Map(this.types);
117
+ }
118
+
119
+ err(msg, node) {
120
+ const e = new TypeCheckError(
121
+ msg,
122
+ node,
123
+ this._currentFile,
124
+ this._currentSource,
125
+ );
126
+ this.errors.push(e);
127
+ return ANY; // recovery type
128
+ }
129
+
130
+ _reportUnused(scope, node) {
131
+ for (const name of scope.unusedLocals()) {
132
+ this.err(`'${name}' declared and not used`, node);
133
+ }
134
+ }
135
+
136
+ _setCurrentFile(p) {
137
+ this._currentFile = p._filename ?? null;
138
+ this._currentSource = p._source ?? null;
139
+ }
140
+
141
+ check(program) {
142
+ this._setCurrentFile(program);
143
+ // Pass 1: collect type declarations
144
+ for (const decl of program.decls) {
145
+ if (decl.kind === "TypeDecl") this.collectType(decl);
146
+ }
147
+ // Pass 2: collect function / method signatures
148
+ for (const decl of program.decls) {
149
+ if (decl.kind === "FuncDecl" || decl.kind === "MethodDecl") {
150
+ this.collectFunc(decl);
151
+ } else if (decl.kind === "TemplDecl") {
152
+ this._collectTemplDecl(decl);
153
+ }
154
+ }
155
+ // Pass 2.1: Promote embedded methods
156
+ this._promoteEmbeddedMethods();
157
+ // Pass 3: check bodies
158
+ for (const decl of program.decls) {
159
+ this.checkTopDecl(decl, this.globals);
160
+ }
161
+ return this.errors;
162
+ }
163
+
164
+ // Pre-declare a package-level var so other files can reference its name
165
+ // before we've type-checked its initializer. Called in pass 2.5.
166
+ collectVar(decl) {
167
+ for (const spec of decl.decls) {
168
+ const type = spec.type
169
+ ? this.resolveTypeNode(spec.type, this.globals)
170
+ : ANY;
171
+ for (const name of spec.names) this.globals.define(name, type);
172
+ }
173
+ }
174
+
175
+ collectConst(decl) {
176
+ for (const spec of decl.decls) {
177
+ const type = spec.type
178
+ ? this.resolveTypeNode(spec.type, this.globals)
179
+ : ANY;
180
+ for (const name of spec.names) this.globals.defineConst(name, type);
181
+ }
182
+ }
183
+
184
+ // Like check() but operates over multiple programs (same-package multi-file).
185
+ // All passes run across all files before moving to the next pass,
186
+ // so every file sees every other file's declarations.
187
+ checkAll(programs) {
188
+ this._collectTypesPass(programs);
189
+ this._collectFuncsPass(programs);
190
+ this._promoteEmbeddedMethods();
191
+ this._collectVarsConstsPass(programs);
192
+ this._checkTopDeclsPass(programs);
193
+ return this.errors;
194
+ }
195
+
196
+ _collectTypesPass(programs) {
197
+ for (const p of programs) {
198
+ this._setCurrentFile(p);
199
+ for (const d of p.decls) if (d.kind === "TypeDecl") this.collectType(d);
200
+ }
201
+ }
202
+
203
+ _collectFuncsPass(programs) {
204
+ for (const p of programs) {
205
+ this._setCurrentFile(p);
206
+ for (const d of p.decls) {
207
+ if (d.kind === "FuncDecl" || d.kind === "MethodDecl")
208
+ this.collectFunc(d);
209
+ else if (d.kind === "TemplDecl") this._collectTemplDecl(d);
210
+ }
211
+ }
212
+ }
213
+
214
+ _collectVarsConstsPass(programs) {
215
+ for (const p of programs) {
216
+ this._setCurrentFile(p);
217
+ for (const d of p.decls) {
218
+ if (d.kind === "VarDecl") this.collectVar(d);
219
+ if (d.kind === "ConstDecl") this.collectConst(d);
220
+ }
221
+ }
222
+ }
223
+
224
+ _checkTopDeclsPass(programs) {
225
+ for (const p of programs) {
226
+ this._setCurrentFile(p);
227
+ for (const d of p.decls) this.checkTopDecl(d, this.globals);
228
+ }
229
+ }
230
+
231
+ // ── Shared pass helpers ──────────────────────────────────────
232
+
233
+ _promoteEmbeddedMethods() {
234
+ for (const type of this.types.values()) {
235
+ const struct = type.underlying;
236
+ if (struct?.kind === "struct" && struct._embeds) {
237
+ for (const embed of struct._embeds) {
238
+ const base = embed.kind === "named" ? embed.underlying : embed;
239
+ if (base?.kind !== "struct" || !base.methods) continue;
240
+ for (const [mName, mType] of base.methods.entries()) {
241
+ if (!struct.methods.has(mName)) struct.methods.set(mName, mType);
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ // ── Type collection ──────────────────────────────────────────
249
+
250
+ collectType(decl) {
251
+ if (decl.typeParams) {
252
+ // Generic type — resolve underlying with type params as ANY for struct fields
253
+ const typeScope = new Scope(this.globals);
254
+ const typeParamTypes = decl.typeParams.map((tp) => {
255
+ const t = {
256
+ kind: "typeParam",
257
+ name: tp.name,
258
+ constraint: tp.constraint,
259
+ };
260
+ typeScope.define(tp.name, t);
261
+ return t;
262
+ });
263
+ const underlying = this.resolveTypeNode(decl.type, typeScope);
264
+ const named = {
265
+ kind: "named",
266
+ name: decl.name,
267
+ underlying,
268
+ _generic: {
269
+ typeParams: typeParamTypes,
270
+ declNode: decl,
271
+ },
272
+ };
273
+ if (underlying.kind === "struct") {
274
+ underlying.name = decl.name;
275
+ underlying.methods = new Map();
276
+ }
277
+ this.types.set(decl.name, named);
278
+ this.globals.define(decl.name, named);
279
+ return;
280
+ }
281
+ const underlying = this.resolveTypeNode(decl.type, this.globals);
282
+ if (decl.isAlias) {
283
+ // type A = B — transparent alias, A and B are identical types
284
+ this.types.set(decl.name, underlying);
285
+ this.globals.define(decl.name, underlying);
286
+ return;
287
+ }
288
+ const named = { kind: "named", name: decl.name, underlying };
289
+ if (underlying.kind === "struct") {
290
+ underlying.name = decl.name;
291
+ underlying.methods = new Map();
292
+ } else if (underlying.kind !== "interface") {
293
+ named.methods = new Map();
294
+ }
295
+ if (underlying.kind === "interface") {
296
+ underlying.name = decl.name;
297
+ }
298
+ this.types.set(decl.name, named);
299
+ this.globals.define(decl.name, named);
300
+ }
301
+
302
+ _buildCollectFuncScope(decl) {
303
+ let resolveScope = this.globals;
304
+ let typeParamTypes = null;
305
+ if (decl.typeParams) {
306
+ resolveScope = new Scope(this.globals);
307
+ typeParamTypes = decl.typeParams.map((tp) => {
308
+ const t = {
309
+ kind: "typeParam",
310
+ name: tp.name,
311
+ constraint: tp.constraint,
312
+ };
313
+ resolveScope.define(tp.name, t);
314
+ return t;
315
+ });
316
+ }
317
+ if (decl.kind === "MethodDecl") {
318
+ const recvNamedType = this.types.get(decl.recvType.name);
319
+ if (recvNamedType?._generic) {
320
+ resolveScope = new Scope(this.globals);
321
+ for (const tp of recvNamedType._generic.typeParams)
322
+ resolveScope.define(tp.name, tp);
323
+ }
324
+ }
325
+ return { resolveScope, typeParamTypes };
326
+ }
327
+
328
+ _registerFuncDecl(decl, funcType, typeParamTypes) {
329
+ if (this.globals.symbols.has(decl.name) && decl.name !== "init")
330
+ this.err(`${decl.name} redeclared in this block`, decl);
331
+ if (typeParamTypes) {
332
+ this.globals.define(decl.name, {
333
+ kind: "generic",
334
+ name: decl.name,
335
+ typeParams: typeParamTypes,
336
+ underlying: funcType,
337
+ });
338
+ } else {
339
+ this.globals.define(decl.name, funcType);
340
+ }
341
+ }
342
+
343
+ collectFunc(decl) {
344
+ const { resolveScope, typeParamTypes } = this._buildCollectFuncScope(decl);
345
+ const paramTypes = decl.params.map((p) =>
346
+ this.resolveTypeNode(p.type, resolveScope),
347
+ );
348
+ const returnType = decl.returnType
349
+ ? this.resolveTypeNode(decl.returnType, resolveScope)
350
+ : VOID;
351
+ const isVariadic =
352
+ decl.params.length > 0 && decl.params[decl.params.length - 1].variadic;
353
+ const funcType = {
354
+ kind: "func",
355
+ params: paramTypes,
356
+ returns: [returnType],
357
+ variadic: isVariadic,
358
+ async: decl.async ?? false,
359
+ };
360
+ if (decl.kind === "FuncDecl")
361
+ this._registerFuncDecl(decl, funcType, typeParamTypes);
362
+ else this._attachMethod(decl, funcType);
363
+ }
364
+
365
+ _attachGenericMethod(recvNamedType, decl, funcType) {
366
+ if (!recvNamedType._generic.methods)
367
+ recvNamedType._generic.methods = new Map();
368
+ recvNamedType._generic.methods.set(decl.name, funcType);
369
+ const base = recvNamedType.underlying;
370
+ if (base?.kind === "struct") base.methods.set(decl.name, funcType);
371
+ }
372
+
373
+ _attachNonGenericMethod(decl, funcType) {
374
+ const recvType = this.resolveTypeNodeName(decl.recvType, this.globals);
375
+ const base = recvType?.underlying ?? recvType;
376
+ if (base?.kind === "struct") {
377
+ base.methods.set(decl.name, funcType);
378
+ } else if (recvType?.kind === "named" && recvType.methods) {
379
+ recvType.methods.set(decl.name, funcType);
380
+ }
381
+ }
382
+
383
+ _attachMethod(decl, funcType) {
384
+ const recvNamedType = this.types.get(decl.recvType.name);
385
+ if (recvNamedType?._generic)
386
+ this._attachGenericMethod(recvNamedType, decl, funcType);
387
+ else this._attachNonGenericMethod(decl, funcType);
388
+ }
389
+
390
+ // ── Top-level checker ────────────────────────────────────────
391
+
392
+ checkTopDecl(decl, scope) {
393
+ switch (decl.kind) {
394
+ case "FuncDecl":
395
+ this.checkFuncDecl(decl, scope);
396
+ break;
397
+ case "MethodDecl":
398
+ this.checkMethodDecl(decl, scope);
399
+ break;
400
+ case "VarDecl":
401
+ this.checkVarDecl(decl, scope);
402
+ break;
403
+ case "ConstDecl":
404
+ this.checkConstDecl(decl, scope);
405
+ break;
406
+ case "TypeDecl":
407
+ case "TemplDecl":
408
+ break; // already collected / no body to check
409
+ }
410
+ }
411
+
412
+ _collectTemplDecl(decl) {
413
+ const paramTypes = decl.params.map((p) =>
414
+ this.resolveTypeNode(p.type, this.globals),
415
+ );
416
+ const gomNodeType = this.types.get("gom.Node") ?? {
417
+ kind: "basic",
418
+ name: "any",
419
+ };
420
+ const isVariadic =
421
+ decl.params.length > 0 && decl.params[decl.params.length - 1].variadic;
422
+ const funcType = {
423
+ kind: "func",
424
+ params: paramTypes,
425
+ returns: [gomNodeType],
426
+ variadic: isVariadic,
427
+ async: false,
428
+ };
429
+ if (this.globals.symbols.has(decl.name) && decl.name !== "init") {
430
+ this.err(`${decl.name} redeclared in this block`, decl);
431
+ }
432
+ this.globals.define(decl.name, funcType);
433
+ }
434
+
435
+ checkFuncDecl(decl, outer) {
436
+ const inner = new Scope(outer);
437
+ this._injectTypeParams(decl, inner, outer);
438
+ for (const p of decl.params) {
439
+ inner.define(p.name, this.resolveTypeNode(p.type, inner));
440
+ }
441
+ const returnType = this._setupFuncReturnType(decl, inner, outer);
442
+ this._runFuncBody(decl, inner, returnType);
443
+ this._checkMissingReturn(decl, returnType, "function");
444
+ }
445
+
446
+ checkMethodDecl(decl, outer) {
447
+ const inner = new Scope(outer);
448
+ const recvTypeName =
449
+ decl.recvType.kind === "GenericTypeName"
450
+ ? decl.recvType.name
451
+ : decl.recvType.name;
452
+ const recvNamedType = this.types.get(recvTypeName);
453
+ this._injectGenericReceiverTypeParams(inner, recvNamedType);
454
+ const recvType = this.resolveTypeNodeName(decl.recvType, outer);
455
+ inner.define(decl.recvName, recvType);
456
+ for (const p of decl.params) {
457
+ inner.define(p.name, this.resolveTypeNode(p.type, inner));
458
+ }
459
+ const returnType = this._setupFuncReturnType(decl, inner, inner);
460
+ this._runFuncBody(decl, inner, returnType);
461
+ this._checkMissingReturn(decl, returnType, "method");
462
+ }
463
+
464
+ _injectTypeParams(decl, inner, outer) {
465
+ if (!decl.typeParams) return;
466
+ for (const tp of decl.typeParams) {
467
+ const constraint = tp.constraint
468
+ ? this.resolveTypeNode(tp.constraint, outer)
469
+ : ANY;
470
+ inner.define(tp.name, { kind: "typeParam", name: tp.name, constraint });
471
+ }
472
+ }
473
+
474
+ _injectGenericReceiverTypeParams(inner, recvNamedType) {
475
+ if (!recvNamedType?._generic) return;
476
+ for (const tp of recvNamedType._generic.typeParams) {
477
+ inner.define(tp.name, tp);
478
+ }
479
+ }
480
+
481
+ _setupFuncReturnType(decl, inner, outer) {
482
+ let returnType = decl.returnType
483
+ ? this.resolveTypeNode(decl.returnType, inner)
484
+ : VOID;
485
+ const hasNamedReturns = this._injectNamedReturns(
486
+ decl.returnType,
487
+ inner,
488
+ outer,
489
+ );
490
+ if (hasNamedReturns && returnType)
491
+ returnType = { ...returnType, _hasNamedReturns: true };
492
+ return returnType;
493
+ }
494
+
495
+ _runFuncBody(decl, inner, returnType) {
496
+ const savedDefer = this._deferCount;
497
+ this._deferCount = 0;
498
+ this.checkBlock(decl.body, inner, returnType);
499
+ this._reportUnused(inner, decl);
500
+ if (this._deferCount > 0) decl.body._hasDefer = true;
501
+ this._deferCount = savedDefer;
502
+ decl._returnType = returnType;
503
+ }
504
+
505
+ _checkMissingReturn(decl, returnType, kind) {
506
+ if (!isVoid(returnType) && !returnType._hasNamedReturns) {
507
+ if (!this._isTerminating(decl.body)) {
508
+ this.err(`missing return at end of ${kind} '${decl.name}'`, decl);
509
+ }
510
+ }
511
+ }
512
+
513
+ _injectNamedReturns(returnTypeNode, scope, outer) {
514
+ if (!returnTypeNode?._namedReturns) return false;
515
+ for (const { name, type } of returnTypeNode._namedReturns) {
516
+ if (name) scope.define(name, this.resolveTypeNode(type, outer));
517
+ }
518
+ return true;
519
+ }
520
+
521
+ checkVarDecl(decl, scope) {
522
+ for (const spec of decl.decls) {
523
+ let type = spec.type ? this.resolveTypeNode(spec.type, scope) : null;
524
+ if (spec.value) {
525
+ const valTypes = spec.value.map((v) => this.checkExpr(v, scope));
526
+ if (!type) type = defaultType(valTypes[0]) ?? ANY;
527
+ for (let i = 0; i < spec.names.length; i++) {
528
+ const vt = valTypes[i] ?? ANY;
529
+ this.assertAssignable(type, vt, spec.value[i]);
530
+ }
531
+ }
532
+ if (!type) type = ANY;
533
+ for (const name of spec.names) scope.defineLocal(name, type);
534
+ }
535
+ }
536
+
537
+ checkConstDecl(decl, scope) {
538
+ for (const spec of decl.decls) {
539
+ const valTypes = spec.value.map((v) => this.checkExpr(v, scope));
540
+ // Explicit type annotation → typed constant; otherwise preserve untyped
541
+ const type = spec.type
542
+ ? this.resolveTypeNode(spec.type, scope)
543
+ : (valTypes[0] ?? ANY);
544
+ for (const name of spec.names) scope.defineConst(name, type);
545
+ }
546
+ }
547
+
548
+ // ── Statement checking ───────────────────────────────────────
549
+ }
550
+
551
+ Object.assign(TypeChecker.prototype, statementCheckMethods);
552
+ Object.assign(TypeChecker.prototype, expressionCheckMethods);
553
+ Object.assign(TypeChecker.prototype, terminationMethods);
554
+ Object.assign(TypeChecker.prototype, resolveMethods);
555
+ Object.assign(TypeChecker.prototype, assignabilityMethods);