@tsonic/frontend 0.0.62 → 0.0.63
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/dist/.tsbuildinfo +1 -1
- package/dist/dependency-graph.d.ts +1 -1
- package/dist/dependency-graph.d.ts.map +1 -1
- package/dist/dependency-graph.js +1 -1
- package/dist/dependency-graph.js.map +1 -1
- package/dist/dotnet-metadata.d.ts +0 -12
- package/dist/dotnet-metadata.d.ts.map +1 -1
- package/dist/dotnet-metadata.js +0 -24
- package/dist/dotnet-metadata.js.map +1 -1
- package/dist/generic-function-values.d.ts +11 -0
- package/dist/generic-function-values.d.ts.map +1 -0
- package/dist/generic-function-values.js +243 -0
- package/dist/generic-function-values.js.map +1 -0
- package/dist/generic-function-values.test.d.ts +2 -0
- package/dist/generic-function-values.test.d.ts.map +1 -0
- package/dist/generic-function-values.test.js +256 -0
- package/dist/generic-function-values.test.js.map +1 -0
- package/dist/graph/extraction/imports.d.ts +5 -0
- package/dist/graph/extraction/imports.d.ts.map +1 -1
- package/dist/graph/extraction/imports.js +30 -0
- package/dist/graph/extraction/imports.js.map +1 -1
- package/dist/graph/extraction/index.d.ts +1 -1
- package/dist/graph/extraction/index.d.ts.map +1 -1
- package/dist/graph/extraction/index.js +1 -1
- package/dist/graph/extraction/index.js.map +1 -1
- package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
- package/dist/graph/extraction/orchestrator.js +16 -2
- package/dist/graph/extraction/orchestrator.js.map +1 -1
- package/dist/graph/extraction.d.ts +1 -1
- package/dist/graph/extraction.d.ts.map +1 -1
- package/dist/graph/extraction.js +1 -1
- package/dist/graph/extraction.js.map +1 -1
- package/dist/ir/binding/binding-factory.d.ts +17 -0
- package/dist/ir/binding/binding-factory.d.ts.map +1 -0
- package/dist/ir/binding/binding-factory.js +765 -0
- package/dist/ir/binding/binding-factory.js.map +1 -0
- package/dist/ir/binding/binding-helpers.d.ts +90 -0
- package/dist/ir/binding/binding-helpers.d.ts.map +1 -0
- package/dist/ir/binding/binding-helpers.js +387 -0
- package/dist/ir/binding/binding-helpers.js.map +1 -0
- package/dist/ir/binding/binding-types.d.ts +203 -0
- package/dist/ir/binding/binding-types.d.ts.map +1 -0
- package/dist/ir/binding/binding-types.js +9 -0
- package/dist/ir/binding/binding-types.js.map +1 -0
- package/dist/ir/binding/index.d.ts +4 -158
- package/dist/ir/binding/index.d.ts.map +1 -1
- package/dist/ir/binding/index.js +3 -1134
- package/dist/ir/binding/index.js.map +1 -1
- package/dist/ir/builder.test.js +223 -0
- package/dist/ir/builder.test.js.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.d.ts +3 -3
- package/dist/ir/converters/anonymous-synthesis.d.ts.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.js +45 -8
- package/dist/ir/converters/anonymous-synthesis.js.map +1 -1
- package/dist/ir/converters/expressions/access/access-converter.d.ts +14 -0
- package/dist/ir/converters/expressions/access/access-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/access-converter.js +141 -0
- package/dist/ir/converters/expressions/access/access-converter.js.map +1 -0
- package/dist/ir/converters/expressions/access/binding-resolution.d.ts +35 -0
- package/dist/ir/converters/expressions/access/binding-resolution.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/binding-resolution.js +384 -0
- package/dist/ir/converters/expressions/access/binding-resolution.js.map +1 -0
- package/dist/ir/converters/expressions/access/member-resolution.d.ts +67 -0
- package/dist/ir/converters/expressions/access/member-resolution.d.ts.map +1 -0
- package/dist/ir/converters/expressions/access/member-resolution.js +262 -0
- package/dist/ir/converters/expressions/access/member-resolution.js.map +1 -0
- package/dist/ir/converters/expressions/access.d.ts +1 -7
- package/dist/ir/converters/expressions/access.d.ts.map +1 -1
- package/dist/ir/converters/expressions/access.js +1 -720
- package/dist/ir/converters/expressions/access.js.map +1 -1
- package/dist/ir/converters/expressions/calls/call-converter.d.ts +23 -0
- package/dist/ir/converters/expressions/calls/call-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/call-converter.js +526 -0
- package/dist/ir/converters/expressions/calls/call-converter.js.map +1 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.d.ts +53 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.js +554 -0
- package/dist/ir/converters/expressions/calls/call-site-analysis.js.map +1 -0
- package/dist/ir/converters/expressions/calls/new-converter.d.ts +21 -0
- package/dist/ir/converters/expressions/calls/new-converter.d.ts.map +1 -0
- package/dist/ir/converters/expressions/calls/new-converter.js +182 -0
- package/dist/ir/converters/expressions/calls/new-converter.js.map +1 -0
- package/dist/ir/converters/expressions/calls.d.ts +2 -28
- package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
- package/dist/ir/converters/expressions/calls.js +2 -1344
- package/dist/ir/converters/expressions/calls.js.map +1 -1
- package/dist/ir/converters/expressions/collections.d.ts.map +1 -1
- package/dist/ir/converters/expressions/collections.js +37 -6
- package/dist/ir/converters/expressions/collections.js.map +1 -1
- package/dist/ir/converters/expressions/functions.js +1 -1
- package/dist/ir/converters/expressions/functions.js.map +1 -1
- package/dist/ir/converters/expressions/helpers.d.ts.map +1 -1
- package/dist/ir/converters/expressions/helpers.js +1 -0
- package/dist/ir/converters/expressions/helpers.js.map +1 -1
- package/dist/ir/converters/expressions/other.d.ts.map +1 -1
- package/dist/ir/converters/expressions/other.js +3 -2
- package/dist/ir/converters/expressions/other.js.map +1 -1
- package/dist/ir/converters/flow-narrowing.d.ts.map +1 -1
- package/dist/ir/converters/flow-narrowing.js +3 -2
- package/dist/ir/converters/flow-narrowing.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.js +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.js +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.d.ts +2 -2
- package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.js +289 -2
- package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
- package/dist/ir/expression-converter.d.ts +0 -1
- package/dist/ir/expression-converter.d.ts.map +1 -1
- package/dist/ir/expression-converter.js +0 -2
- package/dist/ir/expression-converter.js.map +1 -1
- package/dist/ir/generic-function-value-lowering.test.d.ts +2 -0
- package/dist/ir/generic-function-value-lowering.test.d.ts.map +1 -0
- package/dist/ir/generic-function-value-lowering.test.js +312 -0
- package/dist/ir/generic-function-value-lowering.test.js.map +1 -0
- package/dist/ir/generic-validator.d.ts +3 -4
- package/dist/ir/generic-validator.d.ts.map +1 -1
- package/dist/ir/generic-validator.js +3 -35
- package/dist/ir/generic-validator.js.map +1 -1
- package/dist/ir/program-context.d.ts +7 -0
- package/dist/ir/program-context.d.ts.map +1 -1
- package/dist/ir/program-context.js +1 -0
- package/dist/ir/program-context.js.map +1 -1
- package/dist/ir/statement-converter.d.ts +0 -2
- package/dist/ir/statement-converter.d.ts.map +1 -1
- package/dist/ir/statement-converter.js +0 -3
- package/dist/ir/statement-converter.js.map +1 -1
- package/dist/ir/type-system/internal/handle-types.d.ts +16 -16
- package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -1
- package/dist/ir/type-system/internal/nominal-env.d.ts +0 -2
- package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -1
- package/dist/ir/type-system/internal/nominal-env.js +2 -6
- package/dist/ir/type-system/internal/nominal-env.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/converter.d.ts +3 -1
- package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/converter.js +3 -1
- package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/objects.js +7 -1
- package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts +0 -2
- package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.js +315 -23
- package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.d.ts +2 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.js +265 -0
- package/dist/ir/type-system/internal/type-converter/orchestrator.test.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/primitives.js +5 -0
- package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/references.js +67 -29
- package/dist/ir/type-system/internal/type-converter/references.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.js +145 -0
- package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.test.js +91 -1
- package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -1
- package/dist/ir/type-system/internal/type-registry.d.ts +1 -1
- package/dist/ir/type-system/internal/type-registry.js +7 -7
- package/dist/ir/type-system/internal/type-registry.js.map +1 -1
- package/dist/ir/type-system/internal/universe/alias-table.d.ts +0 -14
- package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/alias-table.js +0 -17
- package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +3 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-catalog.js +4 -1044
- package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -1
- package/dist/ir/type-system/internal/universe/clr-entry-converter.d.ts +51 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.js +657 -0
- package/dist/ir/type-system/internal/universe/clr-entry-converter.js.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.d.ts +52 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.js +415 -0
- package/dist/ir/type-system/internal/universe/clr-type-parser.js.map +1 -0
- package/dist/ir/type-system/internal/universe/index.d.ts +1 -1
- package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -1
- package/dist/ir/type-system/internal/universe/index.js +1 -3
- package/dist/ir/type-system/internal/universe/index.js.map +1 -1
- package/dist/ir/type-system/internal/universe/unified-universe.test.js +2 -0
- package/dist/ir/type-system/internal/universe/unified-universe.test.js.map +1 -1
- package/dist/ir/type-system/type-system-call-resolution.d.ts +69 -0
- package/dist/ir/type-system/type-system-call-resolution.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-call-resolution.js +1121 -0
- package/dist/ir/type-system/type-system-call-resolution.js.map +1 -0
- package/dist/ir/type-system/type-system-inference.d.ts +98 -0
- package/dist/ir/type-system/type-system-inference.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-inference.js +1083 -0
- package/dist/ir/type-system/type-system-inference.js.map +1 -0
- package/dist/ir/type-system/type-system-relations.d.ts +15 -0
- package/dist/ir/type-system/type-system-relations.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-relations.js +152 -0
- package/dist/ir/type-system/type-system-relations.js.map +1 -0
- package/dist/ir/type-system/type-system-state.d.ts +436 -0
- package/dist/ir/type-system/type-system-state.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-state.js +212 -0
- package/dist/ir/type-system/type-system-state.js.map +1 -0
- package/dist/ir/type-system/type-system-utilities.d.ts +56 -0
- package/dist/ir/type-system/type-system-utilities.d.ts.map +1 -0
- package/dist/ir/type-system/type-system-utilities.js +373 -0
- package/dist/ir/type-system/type-system-utilities.js.map +1 -0
- package/dist/ir/type-system/type-system.d.ts +17 -358
- package/dist/ir/type-system/type-system.d.ts.map +1 -1
- package/dist/ir/type-system/type-system.js +67 -2945
- package/dist/ir/type-system/type-system.js.map +1 -1
- package/dist/ir/types/index.d.ts +1 -0
- package/dist/ir/types/index.d.ts.map +1 -1
- package/dist/ir/types/index.js +1 -0
- package/dist/ir/types/index.js.map +1 -1
- package/dist/ir/types/ir-substitution.js +1 -1
- package/dist/ir/types/ir-substitution.js.map +1 -1
- package/dist/ir/types/statements.d.ts +1 -1
- package/dist/ir/types/type-ops.d.ts +9 -0
- package/dist/ir/types/type-ops.d.ts.map +1 -0
- package/dist/ir/types/type-ops.js +134 -0
- package/dist/ir/types/type-ops.js.map +1 -0
- package/dist/ir/types/type-ops.test.d.ts +2 -0
- package/dist/ir/types/type-ops.test.d.ts.map +1 -0
- package/dist/ir/types/type-ops.test.js +73 -0
- package/dist/ir/types/type-ops.test.js.map +1 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.d.ts +58 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.js +284 -0
- package/dist/ir/validation/attribute-collection/arg-extractor.js.map +1 -0
- package/dist/ir/validation/attribute-collection/marker-parser.d.ts +28 -0
- package/dist/ir/validation/attribute-collection/marker-parser.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/marker-parser.js +404 -0
- package/dist/ir/validation/attribute-collection/marker-parser.js.map +1 -0
- package/dist/ir/validation/attribute-collection/orchestrator.d.ts +28 -0
- package/dist/ir/validation/attribute-collection/orchestrator.d.ts.map +1 -0
- package/dist/ir/validation/attribute-collection/orchestrator.js +332 -0
- package/dist/ir/validation/attribute-collection/orchestrator.js.map +1 -0
- package/dist/ir/validation/attribute-collection-pass.d.ts +1 -23
- package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.js +1 -961
- package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.test.js +12 -6
- package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
- package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
- package/dist/ir/validation/soundness-gate.js +2 -1
- package/dist/ir/validation/soundness-gate.js.map +1 -1
- package/dist/ir/validation/soundness-gate.test.js +69 -0
- package/dist/ir/validation/soundness-gate.test.js.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.d.ts +11 -5
- package/dist/ir/validation/yield-lowering-pass.d.ts.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.js +942 -48
- package/dist/ir/validation/yield-lowering-pass.js.map +1 -1
- package/dist/ir/validation/yield-lowering-pass.test.js +1333 -127
- package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
- package/dist/program/binding-loader.d.ts +37 -0
- package/dist/program/binding-loader.d.ts.map +1 -0
- package/dist/program/binding-loader.js +155 -0
- package/dist/program/binding-loader.js.map +1 -0
- package/dist/program/binding-registry.d.ts +106 -0
- package/dist/program/binding-registry.d.ts.map +1 -0
- package/dist/program/binding-registry.js +590 -0
- package/dist/program/binding-registry.js.map +1 -0
- package/dist/program/binding-types.d.ts +166 -0
- package/dist/program/binding-types.d.ts.map +1 -0
- package/dist/program/binding-types.js +57 -0
- package/dist/program/binding-types.js.map +1 -0
- package/dist/program/bindings.d.ts +6 -271
- package/dist/program/bindings.d.ts.map +1 -1
- package/dist/program/bindings.js +7 -781
- package/dist/program/bindings.js.map +1 -1
- package/dist/resolver/clr-bindings-resolver.d.ts +0 -1
- package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
- package/dist/resolver/clr-bindings-resolver.js +22 -32
- package/dist/resolver/clr-bindings-resolver.js.map +1 -1
- package/dist/resolver/clr-bindings-resolver.test.js +0 -27
- package/dist/resolver/clr-bindings-resolver.test.js.map +1 -1
- package/dist/resolver/import-resolution.d.ts +1 -1
- package/dist/resolver/import-resolution.d.ts.map +1 -1
- package/dist/resolver/import-resolution.js +2 -7
- package/dist/resolver/import-resolution.js.map +1 -1
- package/dist/resolver/naming.d.ts.map +1 -1
- package/dist/resolver/naming.js +1 -0
- package/dist/resolver/naming.js.map +1 -1
- package/dist/types/diagnostic.d.ts +1 -1
- package/dist/types/diagnostic.d.ts.map +1 -1
- package/dist/types/diagnostic.js.map +1 -1
- package/dist/validation/features.d.ts.map +1 -1
- package/dist/validation/features.js +38 -13
- package/dist/validation/features.js.map +1 -1
- package/dist/validation/features.test.d.ts +2 -0
- package/dist/validation/features.test.d.ts.map +1 -0
- package/dist/validation/features.test.js +273 -0
- package/dist/validation/features.test.js.map +1 -0
- package/dist/validation/generics.d.ts +1 -1
- package/dist/validation/generics.d.ts.map +1 -1
- package/dist/validation/generics.js +2 -26
- package/dist/validation/generics.js.map +1 -1
- package/dist/validation/imports.d.ts.map +1 -1
- package/dist/validation/imports.js +2 -1
- package/dist/validation/imports.js.map +1 -1
- package/dist/validation/imports.test.d.ts +2 -0
- package/dist/validation/imports.test.d.ts.map +1 -0
- package/dist/validation/imports.test.js +112 -0
- package/dist/validation/imports.test.js.map +1 -0
- package/dist/validation/static-safety.d.ts +6 -6
- package/dist/validation/static-safety.d.ts.map +1 -1
- package/dist/validation/static-safety.js +163 -109
- package/dist/validation/static-safety.js.map +1 -1
- package/dist/validation/unsupported-utility-types.d.ts +3 -3
- package/dist/validation/unsupported-utility-types.d.ts.map +1 -1
- package/dist/validation/unsupported-utility-types.js +4 -7
- package/dist/validation/unsupported-utility-types.js.map +1 -1
- package/dist/validator.maximus.test.d.ts +2 -0
- package/dist/validator.maximus.test.d.ts.map +1 -0
- package/dist/validator.maximus.test.js +1214 -0
- package/dist/validator.maximus.test.js.map +1 -0
- package/dist/validator.test.js +152 -18
- package/dist/validator.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/ir/converters/statements/declarations/registry.d.ts +0 -96
- package/dist/ir/converters/statements/declarations/registry.d.ts.map +0 -1
- package/dist/ir/converters/statements/declarations/registry.js +0 -130
- package/dist/ir/converters/statements/declarations/registry.js.map +0 -1
- package/dist/ir/this-parameter-inference.test.d.ts +0 -13
- package/dist/ir/this-parameter-inference.test.d.ts.map +0 -1
- package/dist/ir/this-parameter-inference.test.js +0 -165
- package/dist/ir/this-parameter-inference.test.js.map +0 -1
- package/dist/metadata/bindings-loader.d.ts +0 -41
- package/dist/metadata/bindings-loader.d.ts.map +0 -1
- package/dist/metadata/bindings-loader.js +0 -308
- package/dist/metadata/bindings-loader.js.map +0 -1
- package/dist/metadata/bindings-loader.test.d.ts +0 -5
- package/dist/metadata/bindings-loader.test.d.ts.map +0 -1
- package/dist/metadata/bindings-loader.test.js +0 -117
- package/dist/metadata/bindings-loader.test.js.map +0 -1
- package/dist/metadata/index.d.ts +0 -8
- package/dist/metadata/index.d.ts.map +0 -1
- package/dist/metadata/index.js +0 -7
- package/dist/metadata/index.js.map +0 -1
- package/dist/metadata/library-loader.d.ts +0 -42
- package/dist/metadata/library-loader.d.ts.map +0 -1
- package/dist/metadata/library-loader.js +0 -126
- package/dist/metadata/library-loader.js.map +0 -1
- package/dist/metadata/loader.d.ts +0 -26
- package/dist/metadata/loader.d.ts.map +0 -1
- package/dist/metadata/loader.js +0 -333
- package/dist/metadata/loader.js.map +0 -1
- package/dist/metadata/loader.test.d.ts +0 -5
- package/dist/metadata/loader.test.d.ts.map +0 -1
- package/dist/metadata/loader.test.js +0 -119
- package/dist/metadata/loader.test.js.map +0 -1
- package/dist/resolver/naming-policy.d.ts +0 -20
- package/dist/resolver/naming-policy.d.ts.map +0 -1
- package/dist/resolver/naming-policy.js +0 -40
- package/dist/resolver/naming-policy.js.map +0 -1
- package/dist/types/bindings.d.ts +0 -153
- package/dist/types/bindings.d.ts.map +0 -1
- package/dist/types/bindings.js +0 -14
- package/dist/types/bindings.js.map +0 -1
- package/dist/types/metadata.d.ts +0 -196
- package/dist/types/metadata.d.ts.map +0 -1
- package/dist/types/metadata.js +0 -10
- package/dist/types/metadata.js.map +0 -1
- package/dist/types/nested-types.d.ts +0 -111
- package/dist/types/nested-types.d.ts.map +0 -1
- package/dist/types/nested-types.js +0 -176
- package/dist/types/nested-types.js.map +0 -1
- package/dist/types/nested-types.test.d.ts +0 -5
- package/dist/types/nested-types.test.d.ts.map +0 -1
- package/dist/types/nested-types.test.js +0 -135
- package/dist/types/nested-types.test.js.map +0 -1
- package/dist/types/ref-parameters.d.ts +0 -123
- package/dist/types/ref-parameters.d.ts.map +0 -1
- package/dist/types/ref-parameters.js +0 -203
- package/dist/types/ref-parameters.js.map +0 -1
- package/dist/types/ref-parameters.test.d.ts +0 -5
- package/dist/types/ref-parameters.test.d.ts.map +0 -1
- package/dist/types/ref-parameters.test.js +0 -147
- package/dist/types/ref-parameters.test.js.map +0 -1
|
@@ -0,0 +1,1214 @@
|
|
|
1
|
+
import { describe, it } from "mocha";
|
|
2
|
+
import { expect } from "chai";
|
|
3
|
+
import * as ts from "typescript";
|
|
4
|
+
import { validateProgram } from "./validator.js";
|
|
5
|
+
import { DotnetMetadataRegistry } from "./dotnet-metadata.js";
|
|
6
|
+
import { BindingRegistry } from "./program/bindings.js";
|
|
7
|
+
import { createClrBindingsResolver } from "./resolver/clr-bindings-resolver.js";
|
|
8
|
+
import { createBinding } from "./ir/binding/index.js";
|
|
9
|
+
const createTestProgram = (source, fileName = "test.ts") => {
|
|
10
|
+
const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
11
|
+
const compilerOptions = {
|
|
12
|
+
target: ts.ScriptTarget.ES2022,
|
|
13
|
+
module: ts.ModuleKind.NodeNext,
|
|
14
|
+
strict: true,
|
|
15
|
+
noEmit: true,
|
|
16
|
+
skipLibCheck: true,
|
|
17
|
+
};
|
|
18
|
+
const host = ts.createCompilerHost(compilerOptions);
|
|
19
|
+
const originalGetSourceFile = host.getSourceFile;
|
|
20
|
+
host.getSourceFile = (name, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
|
|
21
|
+
if (name === fileName) {
|
|
22
|
+
return sourceFile;
|
|
23
|
+
}
|
|
24
|
+
return originalGetSourceFile.call(host, name, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
25
|
+
};
|
|
26
|
+
const program = ts.createProgram([fileName], compilerOptions, host);
|
|
27
|
+
const checker = program.getTypeChecker();
|
|
28
|
+
return {
|
|
29
|
+
program,
|
|
30
|
+
checker,
|
|
31
|
+
options: {
|
|
32
|
+
projectRoot: "/test",
|
|
33
|
+
sourceRoot: "/test",
|
|
34
|
+
rootNamespace: "Test",
|
|
35
|
+
},
|
|
36
|
+
sourceFiles: [sourceFile],
|
|
37
|
+
declarationSourceFiles: [],
|
|
38
|
+
metadata: new DotnetMetadataRegistry(),
|
|
39
|
+
bindings: new BindingRegistry(),
|
|
40
|
+
clrResolver: createClrBindingsResolver("/test"),
|
|
41
|
+
binding: createBinding(checker),
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const collectCodes = (source) => validateProgram(createTestProgram(source)).diagnostics.map((d) => d.code);
|
|
45
|
+
const hasCode = (source, code) => collectCodes(source).includes(code);
|
|
46
|
+
describe("Maximus Validation Coverage", () => {
|
|
47
|
+
describe("TSN2001 / TSN3011 end-to-end feature gating", () => {
|
|
48
|
+
const shouldReject = [
|
|
49
|
+
{
|
|
50
|
+
name: "with statement",
|
|
51
|
+
code: "TSN2001",
|
|
52
|
+
source: `
|
|
53
|
+
const scope = { x: 1 };
|
|
54
|
+
with (scope) { console.log(x); }
|
|
55
|
+
`,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "unsupported import.meta field",
|
|
59
|
+
code: "TSN2001",
|
|
60
|
+
source: `
|
|
61
|
+
const env = import.meta.env;
|
|
62
|
+
console.log(env);
|
|
63
|
+
`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "dynamic import",
|
|
67
|
+
code: "TSN2001",
|
|
68
|
+
source: `
|
|
69
|
+
async function load() { return import("./module.js"); }
|
|
70
|
+
void load();
|
|
71
|
+
`,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
for (const scenario of shouldReject) {
|
|
75
|
+
it(`rejects ${scenario.name}`, () => {
|
|
76
|
+
expect(hasCode(scenario.source, scenario.code)).to.equal(true);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const shouldAllow = [
|
|
80
|
+
{
|
|
81
|
+
name: "import.meta.url",
|
|
82
|
+
source: `
|
|
83
|
+
const url = import.meta.url;
|
|
84
|
+
console.log(url);
|
|
85
|
+
`,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "import.meta.filename",
|
|
89
|
+
source: `
|
|
90
|
+
const file = import.meta.filename;
|
|
91
|
+
console.log(file);
|
|
92
|
+
`,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "import.meta.dirname",
|
|
96
|
+
source: `
|
|
97
|
+
const dir = import.meta.dirname;
|
|
98
|
+
console.log(dir);
|
|
99
|
+
`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "class method named then",
|
|
103
|
+
source: `
|
|
104
|
+
class Builder {
|
|
105
|
+
then(v: number): number { return v + 1; }
|
|
106
|
+
}
|
|
107
|
+
new Builder().then(1);
|
|
108
|
+
`,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "class method named catch",
|
|
112
|
+
source: `
|
|
113
|
+
class Catcher {
|
|
114
|
+
catch(v: number): number { return v + 1; }
|
|
115
|
+
}
|
|
116
|
+
new Catcher().catch(1);
|
|
117
|
+
`,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "class method named finally",
|
|
121
|
+
source: `
|
|
122
|
+
class Finalizer {
|
|
123
|
+
finally(v: number): number { return v + 1; }
|
|
124
|
+
}
|
|
125
|
+
new Finalizer().finally(1);
|
|
126
|
+
`,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "static import declaration",
|
|
130
|
+
source: `
|
|
131
|
+
import { value } from "./module.js";
|
|
132
|
+
console.log(value);
|
|
133
|
+
`,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "dynamic import side-effect form",
|
|
137
|
+
source: `
|
|
138
|
+
async function load() {
|
|
139
|
+
await import("./module.js");
|
|
140
|
+
}
|
|
141
|
+
void load();
|
|
142
|
+
`,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "Promise.then chain",
|
|
146
|
+
source: `
|
|
147
|
+
const p: Promise<number> = Promise.resolve(1);
|
|
148
|
+
p.then((x) => x + 1);
|
|
149
|
+
`,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "Promise.catch chain",
|
|
153
|
+
source: `
|
|
154
|
+
const p: Promise<number> = Promise.resolve(1);
|
|
155
|
+
p.catch(() => 0);
|
|
156
|
+
`,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "Promise.finally chain",
|
|
160
|
+
source: `
|
|
161
|
+
const p: Promise<number> = Promise.resolve(1);
|
|
162
|
+
p.finally(() => {});
|
|
163
|
+
`,
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
for (const scenario of shouldAllow) {
|
|
167
|
+
it(`does not falsely reject ${scenario.name}`, () => {
|
|
168
|
+
const codes = collectCodes(scenario.source);
|
|
169
|
+
expect(codes.includes("TSN2001")).to.equal(false);
|
|
170
|
+
expect(codes.includes("TSN3011")).to.equal(false);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
describe("Mixed variadic tuples", () => {
|
|
175
|
+
const allowCases = [
|
|
176
|
+
{
|
|
177
|
+
name: "[string, ...number[]]",
|
|
178
|
+
source: `type T = [string, ...number[]];`,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "[number, ...string[], boolean]",
|
|
182
|
+
source: `type T = [number, ...string[], boolean];`,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "rest parameter with mixed tuple",
|
|
186
|
+
source: `function f(...args: [string, ...number[]]): void { void args; }`,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: "generic head + variadic tail",
|
|
190
|
+
source: `type T<U extends unknown[]> = [string, ...U];`,
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "generic variadic head + fixed tail",
|
|
194
|
+
source: `type T<U extends unknown[]> = [...U, string];`,
|
|
195
|
+
},
|
|
196
|
+
{ name: "fixed tuple", source: `type T = [string, number];` },
|
|
197
|
+
{ name: "pure variadic tuple", source: `type T = [...number[]];` },
|
|
198
|
+
{
|
|
199
|
+
name: "generic pure variadic tuple",
|
|
200
|
+
source: `type T<U extends unknown[]> = [...U];`,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "plain rest parameter",
|
|
204
|
+
source: `function f(...args: number[]): void { void args; }`,
|
|
205
|
+
},
|
|
206
|
+
{ name: "empty tuple", source: `type T = [];` },
|
|
207
|
+
{ name: "single fixed tuple element", source: `type T = [string];` },
|
|
208
|
+
];
|
|
209
|
+
for (const c of allowCases) {
|
|
210
|
+
it(`allows ${c.name}`, () => {
|
|
211
|
+
expect(hasCode(c.source, "TSN7408")).to.equal(false);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
describe("infer keyword support", () => {
|
|
216
|
+
const allowCases = [
|
|
217
|
+
{
|
|
218
|
+
name: "simple infer in conditional",
|
|
219
|
+
source: `type Unwrap<T> = T extends Promise<infer U> ? U : T;`,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: "infer in tuple extraction",
|
|
223
|
+
source: `type Head<T> = T extends [infer H, ...unknown[]] ? H : never;`,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: "infer in function return extraction",
|
|
227
|
+
source: `type Return<T> = T extends (...args: never[]) => infer R ? R : never;`,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: "infer in nested conditional",
|
|
231
|
+
source: `type Deep<T> = T extends Promise<infer U> ? (U extends Promise<infer V> ? V : U) : T;`,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: "multiple infer clauses",
|
|
235
|
+
source: `type Pair<T> = T extends [infer A, infer B] ? [A, B] : never;`,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "identifier containing infer",
|
|
239
|
+
source: `const inferredValue = 1; console.log(inferredValue);`,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: "interface property named infer",
|
|
243
|
+
source: `interface X { infer: string; } const x: X = { infer: "ok" };`,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: "simple conditional without infer",
|
|
247
|
+
source: `type T<U> = U extends string ? 1 : 2;`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: "generic alias without conditional",
|
|
251
|
+
source: `type Mapper<T> = { value: T };`,
|
|
252
|
+
},
|
|
253
|
+
];
|
|
254
|
+
for (const c of allowCases) {
|
|
255
|
+
it(`allows ${c.name}`, () => {
|
|
256
|
+
expect(hasCode(c.source, "TSN7409")).to.equal(false);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
describe("mapped and conditional type syntax", () => {
|
|
261
|
+
const allowCases = [
|
|
262
|
+
{
|
|
263
|
+
name: "direct mapped type alias",
|
|
264
|
+
source: `
|
|
265
|
+
type Mapper<T> = { [K in keyof T]: T[K] };
|
|
266
|
+
type X = Mapper<{ a: string; b: number }>;
|
|
267
|
+
`,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
name: "direct conditional type alias",
|
|
271
|
+
source: `
|
|
272
|
+
type C<T> = T extends string ? number : boolean;
|
|
273
|
+
type A = C<string>;
|
|
274
|
+
type B = C<number>;
|
|
275
|
+
`,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: "mapped + conditional with infer",
|
|
279
|
+
source: `
|
|
280
|
+
type Normalize<T> = {
|
|
281
|
+
[K in keyof T]: T[K] extends Promise<infer U> ? U : T[K]
|
|
282
|
+
};
|
|
283
|
+
type N = Normalize<{ a: Promise<number>; b: string }>;
|
|
284
|
+
`,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
name: "parenthesized mapped type syntax",
|
|
288
|
+
source: `
|
|
289
|
+
type Mapper<T> = ({ [K in keyof T]: T[K] });
|
|
290
|
+
type X = Mapper<{ a: string }>;
|
|
291
|
+
`,
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
name: "parenthesized conditional syntax",
|
|
295
|
+
source: `
|
|
296
|
+
type C<T> = (T extends string ? number : boolean);
|
|
297
|
+
type A = C<string>;
|
|
298
|
+
`,
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "mapped syntax in interface member",
|
|
302
|
+
source: `
|
|
303
|
+
type M<T> = { [K in keyof T]: T[K] };
|
|
304
|
+
interface Box {
|
|
305
|
+
map: M<{ a: string; b: number }>;
|
|
306
|
+
}
|
|
307
|
+
const box: Box = { map: { a: "ok", b: 1 } };
|
|
308
|
+
void box;
|
|
309
|
+
`,
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "conditional syntax in generic constraint position",
|
|
313
|
+
source: `
|
|
314
|
+
type Normalize<T> = T extends Promise<infer U> ? U : T;
|
|
315
|
+
function f<T>(x: Normalize<T>): void { void x; }
|
|
316
|
+
`,
|
|
317
|
+
},
|
|
318
|
+
];
|
|
319
|
+
for (const c of allowCases) {
|
|
320
|
+
it(`allows ${c.name}`, () => {
|
|
321
|
+
expect(hasCode(c.source, "TSN7406")).to.equal(false);
|
|
322
|
+
expect(hasCode(c.source, "TSN7407")).to.equal(false);
|
|
323
|
+
expect(hasCode(c.source, "TSN7409")).to.equal(false);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
describe("generic function values (TSN7432 narrowing)", () => {
|
|
328
|
+
const allowCases = [
|
|
329
|
+
{
|
|
330
|
+
name: "module-level const generic arrow with direct call",
|
|
331
|
+
source: `
|
|
332
|
+
const id = <T>(x: T): T => x;
|
|
333
|
+
const n = id<number>(1);
|
|
334
|
+
void n;
|
|
335
|
+
`,
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
name: "module-level const generic function expression with direct call",
|
|
339
|
+
source: `
|
|
340
|
+
const id = function <T>(x: T): T { return x; };
|
|
341
|
+
const s = id<string>("x");
|
|
342
|
+
void s;
|
|
343
|
+
`,
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: "module-level generic value with direct call and export specifier",
|
|
347
|
+
source: `
|
|
348
|
+
const id = <T>(x: T): T => x;
|
|
349
|
+
export { id };
|
|
350
|
+
const s = id<string>("x");
|
|
351
|
+
void s;
|
|
352
|
+
`,
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
name: "module-level generic value with typeof usage",
|
|
356
|
+
source: `
|
|
357
|
+
const id = <T>(x: T): T => x;
|
|
358
|
+
type IdFn = typeof id;
|
|
359
|
+
const s = id<string>("x");
|
|
360
|
+
void s;
|
|
361
|
+
type Alias = IdFn;
|
|
362
|
+
const marker: Alias | undefined = undefined;
|
|
363
|
+
void marker;
|
|
364
|
+
`,
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: "generic function declaration with direct call",
|
|
368
|
+
source: `
|
|
369
|
+
function id<T>(x: T): T { return x; }
|
|
370
|
+
const n = id<number>(1);
|
|
371
|
+
void n;
|
|
372
|
+
`,
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
name: "const alias to generic value with direct generic call",
|
|
376
|
+
source: `
|
|
377
|
+
const id = <T>(x: T): T => x;
|
|
378
|
+
const copy = id;
|
|
379
|
+
const n = copy<number>(1);
|
|
380
|
+
void n;
|
|
381
|
+
`,
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: "const alias to generic function declaration with direct call",
|
|
385
|
+
source: `
|
|
386
|
+
function id<T>(x: T): T { return x; }
|
|
387
|
+
const copy = id;
|
|
388
|
+
const n = copy<number>(1);
|
|
389
|
+
void n;
|
|
390
|
+
`,
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: "chained const aliases to generic value",
|
|
394
|
+
source: `
|
|
395
|
+
const id = <T>(x: T): T => x;
|
|
396
|
+
const copy = id;
|
|
397
|
+
const finalCopy = copy;
|
|
398
|
+
const n = finalCopy<number>(1);
|
|
399
|
+
void n;
|
|
400
|
+
`,
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: "let alias to generic value without reassignment",
|
|
404
|
+
source: `
|
|
405
|
+
const id = <T>(x: T): T => x;
|
|
406
|
+
let copy = id;
|
|
407
|
+
const n = copy<number>(1);
|
|
408
|
+
void n;
|
|
409
|
+
`,
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
name: "nested generic arrow value inside function scope with direct call",
|
|
413
|
+
source: `
|
|
414
|
+
function wrap(): void {
|
|
415
|
+
const id = <T>(x: T): T => x;
|
|
416
|
+
void id<number>(1);
|
|
417
|
+
}
|
|
418
|
+
void wrap;
|
|
419
|
+
`,
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
name: "module-level let generic value with no reassignment",
|
|
423
|
+
source: `
|
|
424
|
+
let id = <T>(x: T): T => x;
|
|
425
|
+
const s = id<string>("x");
|
|
426
|
+
void s;
|
|
427
|
+
`,
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
name: "outer let generic value with reassigned shadow remains valid",
|
|
431
|
+
source: `
|
|
432
|
+
let id = <T>(x: T): T => x;
|
|
433
|
+
{
|
|
434
|
+
let id = 1;
|
|
435
|
+
id = 2;
|
|
436
|
+
void id;
|
|
437
|
+
}
|
|
438
|
+
const s = id<string>("outer");
|
|
439
|
+
void s;
|
|
440
|
+
`,
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "generic value passed in monomorphic callable argument context",
|
|
444
|
+
source: `
|
|
445
|
+
const id = <T>(x: T): T => x;
|
|
446
|
+
function use(fn: (x: number) => number): number {
|
|
447
|
+
return fn(1);
|
|
448
|
+
}
|
|
449
|
+
const out = use(id);
|
|
450
|
+
void out;
|
|
451
|
+
`,
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
name: "generic value assigned to monomorphic callable context",
|
|
455
|
+
source: `
|
|
456
|
+
const id = <T>(x: T): T => x;
|
|
457
|
+
const copy: (x: number) => number = id;
|
|
458
|
+
const out = copy(2);
|
|
459
|
+
void out;
|
|
460
|
+
`,
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
name: "generic value asserted to monomorphic callable context",
|
|
464
|
+
source: `
|
|
465
|
+
const id = <T>(x: T): T => x;
|
|
466
|
+
const copy = id as (x: number) => number;
|
|
467
|
+
const out = copy(2);
|
|
468
|
+
void out;
|
|
469
|
+
`,
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
name: "generic value in parenthesized monomorphic callable context",
|
|
473
|
+
source: `
|
|
474
|
+
const id = <T>(x: T): T => x;
|
|
475
|
+
const copy: (x: number) => number = (id);
|
|
476
|
+
const out = copy(2);
|
|
477
|
+
void out;
|
|
478
|
+
`,
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "generic value in typed object/array callable contexts",
|
|
482
|
+
source: `
|
|
483
|
+
const id = <T>(x: T): T => x;
|
|
484
|
+
type Box = { run: (x: number) => number };
|
|
485
|
+
const box: Box = { run: id };
|
|
486
|
+
const handlers: Array<(x: number) => number> = [id];
|
|
487
|
+
const out = box.run(handlers[0]!(3));
|
|
488
|
+
void out;
|
|
489
|
+
`,
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
name: "generic value in typed object shorthand callable context",
|
|
493
|
+
source: `
|
|
494
|
+
const id = <T>(x: T): T => x;
|
|
495
|
+
type Box = { id: (x: number) => number };
|
|
496
|
+
const box: Box = { id };
|
|
497
|
+
const out = box.id(5);
|
|
498
|
+
void out;
|
|
499
|
+
`,
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
name: "generic value returned through monomorphic callable return type",
|
|
503
|
+
source: `
|
|
504
|
+
function make(): (x: number) => number {
|
|
505
|
+
const id = <T>(x: T): T => x;
|
|
506
|
+
return id;
|
|
507
|
+
}
|
|
508
|
+
const out = make()(4);
|
|
509
|
+
void out;
|
|
510
|
+
`,
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
name: "generic value in monomorphic callable conditional return",
|
|
514
|
+
source: `
|
|
515
|
+
function pick(flag: boolean): (x: number) => number {
|
|
516
|
+
const id = <T>(x: T): T => x;
|
|
517
|
+
const inc = (x: number): number => x + 1;
|
|
518
|
+
return flag ? id : inc;
|
|
519
|
+
}
|
|
520
|
+
const out = pick(true)(2);
|
|
521
|
+
void out;
|
|
522
|
+
`,
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: "generic function value as default export expression",
|
|
526
|
+
source: `
|
|
527
|
+
const id = <T>(x: T): T => x;
|
|
528
|
+
export default id;
|
|
529
|
+
void id<number>(1);
|
|
530
|
+
`,
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
name: "generic function value in multi-declarator const statement",
|
|
534
|
+
source: `
|
|
535
|
+
const id = <T>(x: T): T => x, other = 1;
|
|
536
|
+
const n = id<number>(1);
|
|
537
|
+
void n;
|
|
538
|
+
void other;
|
|
539
|
+
`,
|
|
540
|
+
},
|
|
541
|
+
];
|
|
542
|
+
for (const c of allowCases) {
|
|
543
|
+
it(`allows ${c.name}`, () => {
|
|
544
|
+
expect(hasCode(c.source, "TSN7432")).to.equal(false);
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
const rejectCases = [
|
|
548
|
+
{
|
|
549
|
+
name: "generic function value used as value (non-call usage)",
|
|
550
|
+
source: `
|
|
551
|
+
const id = <T>(x: T): T => x;
|
|
552
|
+
const copy = id;
|
|
553
|
+
void copy;
|
|
554
|
+
`,
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
name: "generic function declaration used as value (non-call usage)",
|
|
558
|
+
source: `
|
|
559
|
+
function id<T>(x: T): T { return x; }
|
|
560
|
+
void id;
|
|
561
|
+
`,
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
name: "generic function value passed as argument",
|
|
565
|
+
source: `
|
|
566
|
+
const id = <T>(x: T): T => x;
|
|
567
|
+
function use(fn: unknown): void { void fn; }
|
|
568
|
+
use(id);
|
|
569
|
+
`,
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
name: "generic function value assigned to generic callable context",
|
|
573
|
+
source: `
|
|
574
|
+
const id = <T>(x: T): T => x;
|
|
575
|
+
const copy: <T>(x: T) => T = id;
|
|
576
|
+
void copy;
|
|
577
|
+
`,
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
name: "generic function value returned from function",
|
|
581
|
+
source: `
|
|
582
|
+
const id = <T>(x: T): T => x;
|
|
583
|
+
function wrap(): unknown { return id; }
|
|
584
|
+
void wrap;
|
|
585
|
+
`,
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
name: "generic function value returned through generic callable return type",
|
|
589
|
+
source: `
|
|
590
|
+
const id = <T>(x: T): T => x;
|
|
591
|
+
function wrap(): <T>(x: T) => T { return id; }
|
|
592
|
+
void wrap;
|
|
593
|
+
`,
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
name: "generic function value in object property position",
|
|
597
|
+
source: `
|
|
598
|
+
const id = <T>(x: T): T => x;
|
|
599
|
+
const obj = { id };
|
|
600
|
+
void obj;
|
|
601
|
+
`,
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
name: "generic function value in array literal position",
|
|
605
|
+
source: `
|
|
606
|
+
const id = <T>(x: T): T => x;
|
|
607
|
+
const arr = [id];
|
|
608
|
+
void arr;
|
|
609
|
+
`,
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
name: "generic function value property access usage",
|
|
613
|
+
source: `
|
|
614
|
+
const id = <T>(x: T): T => x;
|
|
615
|
+
const n = id.name;
|
|
616
|
+
void n;
|
|
617
|
+
`,
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
name: "reassigned let generic function value",
|
|
621
|
+
source: `
|
|
622
|
+
let id = <T>(x: T): T => x;
|
|
623
|
+
id = <T>(x: T): T => x;
|
|
624
|
+
void id<string>("x");
|
|
625
|
+
`,
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
name: "destructuring-reassigned let generic function value",
|
|
629
|
+
source: `
|
|
630
|
+
let id = <T>(x: T): T => x;
|
|
631
|
+
[id] = [id];
|
|
632
|
+
void id<string>("x");
|
|
633
|
+
`,
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: "for-of-target let generic function value",
|
|
637
|
+
source: `
|
|
638
|
+
let id = <T>(x: T): T => x;
|
|
639
|
+
const handlers = [id];
|
|
640
|
+
for (id of handlers) {
|
|
641
|
+
void id<string>("x");
|
|
642
|
+
}
|
|
643
|
+
`,
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
name: "reassigned let alias to generic function value",
|
|
647
|
+
source: `
|
|
648
|
+
const id = <T>(x: T): T => x;
|
|
649
|
+
let copy = id;
|
|
650
|
+
copy = id;
|
|
651
|
+
void copy<string>("x");
|
|
652
|
+
`,
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
name: "var alias to generic function value",
|
|
656
|
+
source: `
|
|
657
|
+
const id = <T>(x: T): T => x;
|
|
658
|
+
var copy = id;
|
|
659
|
+
void copy<string>("x");
|
|
660
|
+
`,
|
|
661
|
+
},
|
|
662
|
+
];
|
|
663
|
+
for (const c of rejectCases) {
|
|
664
|
+
it(`rejects ${c.name}`, () => {
|
|
665
|
+
expect(hasCode(c.source, "TSN7432")).to.equal(true);
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
describe("Array constructor inference", () => {
|
|
670
|
+
const allowCases = [
|
|
671
|
+
{ name: "new Array()", source: `const a = new Array();` },
|
|
672
|
+
{ name: "new Array(10)", source: `const a = new Array(10);` },
|
|
673
|
+
{ name: "new Array('a', 'b')", source: `const a = new Array("a", "b");` },
|
|
674
|
+
{
|
|
675
|
+
name: "new Array(...spread)",
|
|
676
|
+
source: `const xs = [1, 2, 3]; const a = new Array(...xs);`,
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
name: "new Array in expression",
|
|
680
|
+
source: `console.log(new Array(3));`,
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
name: "new Array inside function",
|
|
684
|
+
source: `function f(): void { const arr = new Array(); console.log(arr); }`,
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
name: "new Array<number>()",
|
|
688
|
+
source: `const a = new Array<number>();`,
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
name: "new Array<number>(10)",
|
|
692
|
+
source: `const a = new Array<number>(10);`,
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
name: "new Array<string>('a', 'b')",
|
|
696
|
+
source: `const a = new Array<string>("a", "b");`,
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
name: "Array() call expression",
|
|
700
|
+
source: `const a = Array(10);`,
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
name: "qualified type named Array",
|
|
704
|
+
source: `
|
|
705
|
+
namespace Custom {
|
|
706
|
+
export class Array {
|
|
707
|
+
constructor(public readonly value: number) {}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
const a = new Custom.Array(1);
|
|
711
|
+
console.log(a.value);
|
|
712
|
+
`,
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
name: "typed factory wrapping Array",
|
|
716
|
+
source: `
|
|
717
|
+
function make(): number[] {
|
|
718
|
+
return new Array<number>(5);
|
|
719
|
+
}
|
|
720
|
+
console.log(make().length);
|
|
721
|
+
`,
|
|
722
|
+
},
|
|
723
|
+
];
|
|
724
|
+
for (const c of allowCases) {
|
|
725
|
+
it(`allows ${c.name}`, () => {
|
|
726
|
+
expect(hasCode(c.source, "TSN7416")).to.equal(false);
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
describe("Empty array literals", () => {
|
|
731
|
+
const allowCases = [
|
|
732
|
+
{ name: "const x = []", source: `const x = [];` },
|
|
733
|
+
{ name: "let x = []", source: `let x = [];` },
|
|
734
|
+
{ name: "var x = []", source: `var x = [];` },
|
|
735
|
+
{
|
|
736
|
+
name: "untyped function local empty array",
|
|
737
|
+
source: `function f(): void { const local = []; console.log(local); }`,
|
|
738
|
+
},
|
|
739
|
+
{ name: "annotated variable", source: `const x: number[] = [];` },
|
|
740
|
+
{ name: "type assertion", source: `const x = [] as number[];` },
|
|
741
|
+
{
|
|
742
|
+
name: "typed function return",
|
|
743
|
+
source: `function f(): number[] { return []; }`,
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
name: "typed function parameter",
|
|
747
|
+
source: `function consume(xs: number[]): void { console.log(xs.length); } consume([]);`,
|
|
748
|
+
},
|
|
749
|
+
{
|
|
750
|
+
name: "typed object property",
|
|
751
|
+
source: `const x: { items: number[] } = { items: [] }; console.log(x.items.length);`,
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
name: "typed conditional expression",
|
|
755
|
+
source: `const x: number[] = true ? [] : []; console.log(x.length);`,
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
name: "untyped conditional expression",
|
|
759
|
+
source: `const x = Math.random() > 0.5 ? [] : []; console.log(x.length);`,
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
name: "untyped nested object property",
|
|
763
|
+
source: `const x = { items: [] }; console.log(x.items.length);`,
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
name: "typed class field initializer",
|
|
767
|
+
source: `class Box { items: number[] = []; } console.log(new Box().items.length);`,
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
name: "return from typed arrow",
|
|
771
|
+
source: `const make: () => number[] = () => []; console.log(make().length);`,
|
|
772
|
+
},
|
|
773
|
+
];
|
|
774
|
+
for (const c of allowCases) {
|
|
775
|
+
it(`allows ${c.name}`, () => {
|
|
776
|
+
expect(hasCode(c.source, "TSN7417")).to.equal(false);
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
describe("TSN7430 - arrow function escape hatch", () => {
|
|
781
|
+
const rejectCases = [
|
|
782
|
+
{ name: "no contextual type", source: `const f = (x) => x + 1;` },
|
|
783
|
+
{ name: "destructuring param", source: `const f = ({ x }) => x;` },
|
|
784
|
+
{ name: "defaulted param", source: `const f = (x = 1) => x;` },
|
|
785
|
+
{ name: "rest param", source: `const f = (...xs) => xs.length;` },
|
|
786
|
+
{
|
|
787
|
+
name: "async arrow without context",
|
|
788
|
+
source: `const f = async (x) => x + 1;`,
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
name: "explicit param but implicit return",
|
|
792
|
+
source: `const f = (x: number) => x + 1;`,
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
name: "nested non-simple arrow",
|
|
796
|
+
source: `const outer = () => ({ run: (...xs) => xs.length });`,
|
|
797
|
+
},
|
|
798
|
+
];
|
|
799
|
+
for (const c of rejectCases) {
|
|
800
|
+
it(`rejects ${c.name}`, () => {
|
|
801
|
+
expect(hasCode(c.source, "TSN7430")).to.equal(true);
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
const allowCases = [
|
|
805
|
+
{
|
|
806
|
+
name: "fully typed arrow",
|
|
807
|
+
source: `const f = (x: number): number => x + 1; console.log(f(1));`,
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
name: "contextual typing via variable annotation",
|
|
811
|
+
source: `
|
|
812
|
+
type Mapper = (x: number) => number;
|
|
813
|
+
const f: Mapper = (x) => x + 1;
|
|
814
|
+
console.log(f(1));
|
|
815
|
+
`,
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
name: "contextual typing via function argument",
|
|
819
|
+
source: `
|
|
820
|
+
const apply = (f: (x: number) => number): number => f(1);
|
|
821
|
+
console.log(apply((x) => x + 1));
|
|
822
|
+
`,
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
name: "contextual typing via array element",
|
|
826
|
+
source: `
|
|
827
|
+
type Op = (a: number, b: number) => number;
|
|
828
|
+
const ops: Op[] = [(a, b) => a + b];
|
|
829
|
+
console.log(ops[0](1, 2));
|
|
830
|
+
`,
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
name: "nested contextual typing via explicit return type",
|
|
834
|
+
source: `
|
|
835
|
+
const factory: () => ((x: number) => number) = () => (x) => x + 1;
|
|
836
|
+
console.log(factory()(1));
|
|
837
|
+
`,
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
name: "simple arrow with explicit param and explicit return",
|
|
841
|
+
source: `const f = (x: number): number => x + 1; console.log(f(1));`,
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
name: "simple arrow with explicit return only",
|
|
845
|
+
source: `const f = (x: number): number => x + 1; console.log(f(1));`,
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
name: "simple arrow in object literal with contextual type",
|
|
849
|
+
source: `
|
|
850
|
+
type Ops = { add: (x: number, y: number) => number };
|
|
851
|
+
const ops: Ops = { add: (x, y) => x + y };
|
|
852
|
+
console.log(ops.add(1, 2));
|
|
853
|
+
`,
|
|
854
|
+
},
|
|
855
|
+
];
|
|
856
|
+
for (const c of allowCases) {
|
|
857
|
+
it(`allows ${c.name}`, () => {
|
|
858
|
+
expect(hasCode(c.source, "TSN7430")).to.equal(false);
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
describe("Dictionary key domains (TSN7413 / TSN7203)", () => {
|
|
863
|
+
const allowCases = [
|
|
864
|
+
{
|
|
865
|
+
name: "Record with symbol key",
|
|
866
|
+
source: `
|
|
867
|
+
type Symbols = Record<symbol, number>;
|
|
868
|
+
const table: Symbols = {} as Symbols;
|
|
869
|
+
void table;
|
|
870
|
+
`,
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
name: "symbol index signature",
|
|
874
|
+
source: `
|
|
875
|
+
interface SymbolMap {
|
|
876
|
+
[key: symbol]: string;
|
|
877
|
+
}
|
|
878
|
+
const table: SymbolMap = {} as SymbolMap;
|
|
879
|
+
void table;
|
|
880
|
+
`,
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
name: "mixed PropertyKey union",
|
|
884
|
+
source: `
|
|
885
|
+
type Dict = Record<string | number | symbol, number>;
|
|
886
|
+
const value: Dict = {} as Dict;
|
|
887
|
+
void value;
|
|
888
|
+
`,
|
|
889
|
+
},
|
|
890
|
+
{
|
|
891
|
+
name: "symbol-typed parameter used for dictionary indexing",
|
|
892
|
+
source: `
|
|
893
|
+
function read(table: Record<symbol, number>, key: symbol): number {
|
|
894
|
+
return table[key];
|
|
895
|
+
}
|
|
896
|
+
void read;
|
|
897
|
+
`,
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
name: "mixed string and symbol dictionary key operations",
|
|
901
|
+
source: `
|
|
902
|
+
function readMixed(
|
|
903
|
+
table: Record<string | symbol, number>,
|
|
904
|
+
key: symbol
|
|
905
|
+
): number {
|
|
906
|
+
table["count"] = 1;
|
|
907
|
+
table[key] = 2;
|
|
908
|
+
return table["count"] + table[key];
|
|
909
|
+
}
|
|
910
|
+
void readMixed;
|
|
911
|
+
`,
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
name: "symbol-key undefined comparison and delete shape",
|
|
915
|
+
source: `
|
|
916
|
+
function prune(table: Record<symbol, number>, key: symbol): boolean {
|
|
917
|
+
if (table[key] !== undefined) {
|
|
918
|
+
delete table[key];
|
|
919
|
+
}
|
|
920
|
+
return table[key] === undefined;
|
|
921
|
+
}
|
|
922
|
+
void prune;
|
|
923
|
+
`,
|
|
924
|
+
},
|
|
925
|
+
];
|
|
926
|
+
for (const c of allowCases) {
|
|
927
|
+
it(`allows ${c.name}`, () => {
|
|
928
|
+
const codes = collectCodes(c.source);
|
|
929
|
+
expect(codes.includes("TSN7413")).to.equal(false);
|
|
930
|
+
expect(codes.includes("TSN7203")).to.equal(false);
|
|
931
|
+
expect(codes.includes("TSN7414")).to.equal(false);
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
const rejectCases = [
|
|
935
|
+
{
|
|
936
|
+
name: "Record with object key type",
|
|
937
|
+
source: `
|
|
938
|
+
interface Key { id: string; }
|
|
939
|
+
type Dict = Record<Key, number>;
|
|
940
|
+
const value: Dict = {} as Dict;
|
|
941
|
+
void value;
|
|
942
|
+
`,
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
name: "index signature with object key type",
|
|
946
|
+
source: `
|
|
947
|
+
interface Key { id: string; }
|
|
948
|
+
interface Dict {
|
|
949
|
+
[key: Key]: number;
|
|
950
|
+
}
|
|
951
|
+
`,
|
|
952
|
+
},
|
|
953
|
+
];
|
|
954
|
+
for (const c of rejectCases) {
|
|
955
|
+
it(`rejects ${c.name}`, () => {
|
|
956
|
+
expect(hasCode(c.source, "TSN7413")).to.equal(true);
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
describe("Object literal synthesis (TSN7403 narrowing)", () => {
|
|
961
|
+
const allowCases = [
|
|
962
|
+
{
|
|
963
|
+
name: "method shorthand without dynamic receiver semantics",
|
|
964
|
+
source: `
|
|
965
|
+
const point = {
|
|
966
|
+
add(x: number, y: number): number {
|
|
967
|
+
return x + y;
|
|
968
|
+
},
|
|
969
|
+
};
|
|
970
|
+
const n = point.add(1, 2);
|
|
971
|
+
void n;
|
|
972
|
+
`,
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: "mixed property assignments and method shorthand",
|
|
976
|
+
source: `
|
|
977
|
+
const obj = {
|
|
978
|
+
base: 2,
|
|
979
|
+
mul(x: number): number {
|
|
980
|
+
return x * 2;
|
|
981
|
+
},
|
|
982
|
+
};
|
|
983
|
+
const n = obj.mul(obj.base);
|
|
984
|
+
void n;
|
|
985
|
+
`,
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
name: "computed string-literal method shorthand",
|
|
989
|
+
source: `
|
|
990
|
+
const obj = {
|
|
991
|
+
["mul"](x: number, y: number): number {
|
|
992
|
+
return x * y;
|
|
993
|
+
},
|
|
994
|
+
};
|
|
995
|
+
const n = obj.mul(2, 3);
|
|
996
|
+
void n;
|
|
997
|
+
`,
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
name: "method shorthand in typed generic call argument",
|
|
1001
|
+
source: `
|
|
1002
|
+
interface Ops {
|
|
1003
|
+
add: (x: number, y: number) => number;
|
|
1004
|
+
}
|
|
1005
|
+
function box<T>(x: T): T { return x; }
|
|
1006
|
+
const ops = box<Ops>({
|
|
1007
|
+
add(x: number, y: number): number {
|
|
1008
|
+
return x + y;
|
|
1009
|
+
},
|
|
1010
|
+
});
|
|
1011
|
+
const n = ops.add(1, 2);
|
|
1012
|
+
void n;
|
|
1013
|
+
`,
|
|
1014
|
+
},
|
|
1015
|
+
];
|
|
1016
|
+
for (const c of allowCases) {
|
|
1017
|
+
it(`allows ${c.name}`, () => {
|
|
1018
|
+
expect(hasCode(c.source, "TSN7403")).to.equal(false);
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
const rejectCases = [
|
|
1022
|
+
{
|
|
1023
|
+
name: "method shorthand using this",
|
|
1024
|
+
source: `
|
|
1025
|
+
const obj = {
|
|
1026
|
+
base: 2,
|
|
1027
|
+
mul(x: number): number {
|
|
1028
|
+
return this.base * x;
|
|
1029
|
+
},
|
|
1030
|
+
};
|
|
1031
|
+
void obj;
|
|
1032
|
+
`,
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
name: "method shorthand using arguments",
|
|
1036
|
+
source: `
|
|
1037
|
+
const obj = {
|
|
1038
|
+
mul(x: number): number {
|
|
1039
|
+
return arguments.length;
|
|
1040
|
+
},
|
|
1041
|
+
};
|
|
1042
|
+
void obj;
|
|
1043
|
+
`,
|
|
1044
|
+
},
|
|
1045
|
+
{
|
|
1046
|
+
name: "method shorthand using super",
|
|
1047
|
+
source: `
|
|
1048
|
+
const base = {
|
|
1049
|
+
mul(x: number): number {
|
|
1050
|
+
return x * 2;
|
|
1051
|
+
},
|
|
1052
|
+
};
|
|
1053
|
+
const obj = {
|
|
1054
|
+
__proto__: base,
|
|
1055
|
+
mul(x: number): number {
|
|
1056
|
+
return super.mul(x);
|
|
1057
|
+
},
|
|
1058
|
+
};
|
|
1059
|
+
void obj;
|
|
1060
|
+
`,
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
name: "getter shorthand in synthesized object literal",
|
|
1064
|
+
source: `
|
|
1065
|
+
const obj = {
|
|
1066
|
+
get value(): number {
|
|
1067
|
+
return 1;
|
|
1068
|
+
},
|
|
1069
|
+
};
|
|
1070
|
+
void obj;
|
|
1071
|
+
`,
|
|
1072
|
+
},
|
|
1073
|
+
];
|
|
1074
|
+
for (const c of rejectCases) {
|
|
1075
|
+
it(`rejects ${c.name}`, () => {
|
|
1076
|
+
expect(hasCode(c.source, "TSN7403")).to.equal(true);
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
describe("Deterministic typing regressions (TSN520x / TSN7414)", () => {
|
|
1081
|
+
const allowCases = [
|
|
1082
|
+
{
|
|
1083
|
+
name: "expected-return generic inference through helper call",
|
|
1084
|
+
source: `
|
|
1085
|
+
type Ok<T> = { ok: true; value: T };
|
|
1086
|
+
function ok<T>(value: T): Ok<T> {
|
|
1087
|
+
return { ok: true, value };
|
|
1088
|
+
}
|
|
1089
|
+
function build(): Ok<{ id: number; name: string }> {
|
|
1090
|
+
return ok({ id: 1, name: "alice" });
|
|
1091
|
+
}
|
|
1092
|
+
void build;
|
|
1093
|
+
`,
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
name: "generic member recovery through interface substitution",
|
|
1097
|
+
source: `
|
|
1098
|
+
interface Box<T> { value: T; }
|
|
1099
|
+
function read<T>(box: Box<T>): T {
|
|
1100
|
+
return box.value;
|
|
1101
|
+
}
|
|
1102
|
+
const n = read<number>({ value: 1 });
|
|
1103
|
+
void n;
|
|
1104
|
+
`,
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
name: "nested contextual object through generic wrapper",
|
|
1108
|
+
source: `
|
|
1109
|
+
interface User {
|
|
1110
|
+
id: number;
|
|
1111
|
+
info: { name: string; active: boolean };
|
|
1112
|
+
}
|
|
1113
|
+
function wrap<T>(value: T): T { return value; }
|
|
1114
|
+
const user = wrap<User>({
|
|
1115
|
+
id: 1,
|
|
1116
|
+
info: { name: "alice", active: true },
|
|
1117
|
+
});
|
|
1118
|
+
void user;
|
|
1119
|
+
`,
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
name: "typed conditional array return with empty literal branch",
|
|
1123
|
+
source: `
|
|
1124
|
+
function pick(flag: boolean): number[] {
|
|
1125
|
+
return flag ? [1, 2, 3] : [];
|
|
1126
|
+
}
|
|
1127
|
+
const xs = pick(true);
|
|
1128
|
+
void xs;
|
|
1129
|
+
`,
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
name: "typed conditional object branch with nullish fallback",
|
|
1133
|
+
source: `
|
|
1134
|
+
interface Profile { name: string; age: number; }
|
|
1135
|
+
function build(flag: boolean): Profile {
|
|
1136
|
+
const base = flag ? { name: "a", age: 1 } : undefined;
|
|
1137
|
+
return base ?? { name: "b", age: 2 };
|
|
1138
|
+
}
|
|
1139
|
+
void build;
|
|
1140
|
+
`,
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
name: "async promise return typing remains deterministic",
|
|
1144
|
+
source: `
|
|
1145
|
+
async function getValue(): Promise<number> {
|
|
1146
|
+
return Promise.resolve(1);
|
|
1147
|
+
}
|
|
1148
|
+
void getValue;
|
|
1149
|
+
`,
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
name: "generic discriminated union constructor helper remains representable",
|
|
1153
|
+
source: `
|
|
1154
|
+
type Result<T> = { ok: true; value: T } | { ok: false; error: string };
|
|
1155
|
+
function ok<T>(value: T): Result<T> {
|
|
1156
|
+
return { ok: true, value };
|
|
1157
|
+
}
|
|
1158
|
+
function run(): Result<{ total: number }> {
|
|
1159
|
+
return ok({ total: 1 });
|
|
1160
|
+
}
|
|
1161
|
+
void run;
|
|
1162
|
+
`,
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
name: "object shorthand + explicit generic call site",
|
|
1166
|
+
source: `
|
|
1167
|
+
interface Payload { id: number; slug: string; }
|
|
1168
|
+
function identity<T>(value: T): T { return value; }
|
|
1169
|
+
const id = 1;
|
|
1170
|
+
const slug = "hello";
|
|
1171
|
+
const payload = identity<Payload>({ id, slug });
|
|
1172
|
+
void payload;
|
|
1173
|
+
`,
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
name: "generic array element member recovery in loop body",
|
|
1177
|
+
source: `
|
|
1178
|
+
interface Item<T> { value: T; }
|
|
1179
|
+
function sum(items: Item<number>[]): number {
|
|
1180
|
+
let total = 0;
|
|
1181
|
+
for (const item of items) {
|
|
1182
|
+
total = total + item.value;
|
|
1183
|
+
}
|
|
1184
|
+
return total;
|
|
1185
|
+
}
|
|
1186
|
+
void sum;
|
|
1187
|
+
`,
|
|
1188
|
+
},
|
|
1189
|
+
{
|
|
1190
|
+
name: "nullable union narrowing through in-operator remains deterministic",
|
|
1191
|
+
source: `
|
|
1192
|
+
type R = { ok: true; value: number } | { ok: false; error: string };
|
|
1193
|
+
function read(r: R): number {
|
|
1194
|
+
if ("error" in r) {
|
|
1195
|
+
return 0;
|
|
1196
|
+
}
|
|
1197
|
+
return r.value;
|
|
1198
|
+
}
|
|
1199
|
+
void read;
|
|
1200
|
+
`,
|
|
1201
|
+
},
|
|
1202
|
+
];
|
|
1203
|
+
for (const c of allowCases) {
|
|
1204
|
+
it(`avoids deterministic diagnostics for ${c.name}`, () => {
|
|
1205
|
+
const codes = collectCodes(c.source);
|
|
1206
|
+
expect(codes.includes("TSN5201")).to.equal(false);
|
|
1207
|
+
expect(codes.includes("TSN5202")).to.equal(false);
|
|
1208
|
+
expect(codes.includes("TSN5203")).to.equal(false);
|
|
1209
|
+
expect(codes.includes("TSN7414")).to.equal(false);
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1214
|
+
//# sourceMappingURL=validator.maximus.test.js.map
|