@tsonic/frontend 0.0.14 → 0.0.16
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/graph/builder.js +2 -2
- package/dist/graph/builder.js.map +1 -1
- package/dist/graph/extraction/imports.js +1 -1
- package/dist/graph/extraction/imports.js.map +1 -1
- package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
- package/dist/graph/extraction/orchestrator.js +3 -2
- package/dist/graph/extraction/orchestrator.js.map +1 -1
- package/dist/ir/binding/index.d.ts +155 -0
- package/dist/ir/binding/index.d.ts.map +1 -0
- package/dist/ir/binding/index.js +1035 -0
- package/dist/ir/binding/index.js.map +1 -0
- package/dist/ir/binding-resolution.test.js +193 -52
- package/dist/ir/binding-resolution.test.js.map +1 -1
- package/dist/ir/bindings-disambiguation.test.d.ts +11 -0
- package/dist/ir/bindings-disambiguation.test.d.ts.map +1 -0
- package/dist/ir/bindings-disambiguation.test.js +416 -0
- package/dist/ir/bindings-disambiguation.test.js.map +1 -0
- package/dist/ir/builder/exports.d.ts +20 -2
- package/dist/ir/builder/exports.d.ts.map +1 -1
- package/dist/ir/builder/exports.js +65 -6
- package/dist/ir/builder/exports.js.map +1 -1
- package/dist/ir/builder/imports.d.ts +9 -5
- package/dist/ir/builder/imports.d.ts.map +1 -1
- package/dist/ir/builder/imports.js +20 -31
- package/dist/ir/builder/imports.js.map +1 -1
- package/dist/ir/builder/orchestrator.d.ts +10 -1
- package/dist/ir/builder/orchestrator.d.ts.map +1 -1
- package/dist/ir/builder/orchestrator.js +32 -15
- package/dist/ir/builder/orchestrator.js.map +1 -1
- package/dist/ir/builder/statements.d.ts +7 -1
- package/dist/ir/builder/statements.d.ts.map +1 -1
- package/dist/ir/builder/statements.js +7 -2
- package/dist/ir/builder/statements.js.map +1 -1
- package/dist/ir/builder/types.d.ts +2 -0
- package/dist/ir/builder/types.d.ts.map +1 -1
- package/dist/ir/builder/validation.d.ts +4 -1
- package/dist/ir/builder/validation.d.ts.map +1 -1
- package/dist/ir/builder/validation.js +37 -37
- package/dist/ir/builder/validation.js.map +1 -1
- package/dist/ir/builder.test.js +55 -112
- package/dist/ir/builder.test.js.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.d.ts +30 -8
- package/dist/ir/converters/anonymous-synthesis.d.ts.map +1 -1
- package/dist/ir/converters/anonymous-synthesis.js +46 -55
- package/dist/ir/converters/anonymous-synthesis.js.map +1 -1
- package/dist/ir/converters/context.d.ts +40 -0
- package/dist/ir/converters/context.d.ts.map +1 -0
- package/dist/ir/converters/context.js +25 -0
- package/dist/ir/converters/context.js.map +1 -0
- package/dist/ir/converters/expressions/access.d.ts +6 -1
- package/dist/ir/converters/expressions/access.d.ts.map +1 -1
- package/dist/ir/converters/expressions/access.js +389 -43
- package/dist/ir/converters/expressions/access.js.map +1 -1
- package/dist/ir/converters/expressions/calls.d.ts +24 -3
- package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
- package/dist/ir/converters/expressions/calls.js +674 -397
- package/dist/ir/converters/expressions/calls.js.map +1 -1
- package/dist/ir/converters/expressions/collections.d.ts +16 -3
- package/dist/ir/converters/expressions/collections.d.ts.map +1 -1
- package/dist/ir/converters/expressions/collections.js +300 -46
- package/dist/ir/converters/expressions/collections.js.map +1 -1
- package/dist/ir/converters/expressions/functions.d.ts +10 -3
- package/dist/ir/converters/expressions/functions.d.ts.map +1 -1
- package/dist/ir/converters/expressions/functions.js +158 -32
- package/dist/ir/converters/expressions/functions.js.map +1 -1
- package/dist/ir/converters/expressions/helpers.d.ts +22 -23
- package/dist/ir/converters/expressions/helpers.d.ts.map +1 -1
- package/dist/ir/converters/expressions/helpers.js +242 -239
- package/dist/ir/converters/expressions/helpers.js.map +1 -1
- package/dist/ir/converters/expressions/index.d.ts +1 -1
- package/dist/ir/converters/expressions/index.d.ts.map +1 -1
- package/dist/ir/converters/expressions/index.js +1 -1
- package/dist/ir/converters/expressions/index.js.map +1 -1
- package/dist/ir/converters/expressions/literals.d.ts +12 -12
- package/dist/ir/converters/expressions/literals.d.ts.map +1 -1
- package/dist/ir/converters/expressions/literals.js +62 -17
- package/dist/ir/converters/expressions/literals.js.map +1 -1
- package/dist/ir/converters/expressions/numeric-recovery.test.d.ts +5 -2
- package/dist/ir/converters/expressions/numeric-recovery.test.d.ts.map +1 -1
- package/dist/ir/converters/expressions/numeric-recovery.test.js +62 -49
- package/dist/ir/converters/expressions/numeric-recovery.test.js.map +1 -1
- package/dist/ir/converters/expressions/operators.d.ts +13 -4
- package/dist/ir/converters/expressions/operators.d.ts.map +1 -1
- package/dist/ir/converters/expressions/operators.js +183 -33
- package/dist/ir/converters/expressions/operators.js.map +1 -1
- package/dist/ir/converters/expressions/other.d.ts +11 -3
- package/dist/ir/converters/expressions/other.d.ts.map +1 -1
- package/dist/ir/converters/expressions/other.js +26 -10
- package/dist/ir/converters/expressions/other.js.map +1 -1
- package/dist/ir/converters/flow-narrowing.d.ts +27 -0
- package/dist/ir/converters/flow-narrowing.d.ts.map +1 -0
- package/dist/ir/converters/flow-narrowing.js +73 -0
- package/dist/ir/converters/flow-narrowing.js.map +1 -0
- package/dist/ir/converters/statements/control/blocks.d.ts +8 -2
- package/dist/ir/converters/statements/control/blocks.d.ts.map +1 -1
- package/dist/ir/converters/statements/control/blocks.js +7 -2
- package/dist/ir/converters/statements/control/blocks.js.map +1 -1
- package/dist/ir/converters/statements/control/conditionals.d.ts +14 -4
- package/dist/ir/converters/statements/control/conditionals.d.ts.map +1 -1
- package/dist/ir/converters/statements/control/conditionals.js +36 -10
- package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
- package/dist/ir/converters/statements/control/exceptions.d.ts +10 -3
- package/dist/ir/converters/statements/control/exceptions.d.ts.map +1 -1
- package/dist/ir/converters/statements/control/exceptions.js +13 -7
- package/dist/ir/converters/statements/control/exceptions.js.map +1 -1
- package/dist/ir/converters/statements/control/loops.d.ts +16 -5
- package/dist/ir/converters/statements/control/loops.d.ts.map +1 -1
- package/dist/ir/converters/statements/control/loops.js +25 -15
- package/dist/ir/converters/statements/control/loops.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/constructors.d.ts +3 -2
- package/dist/ir/converters/statements/declarations/classes/constructors.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/constructors.js +11 -7
- package/dist/ir/converters/statements/declarations/classes/constructors.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.d.ts +2 -1
- package/dist/ir/converters/statements/declarations/classes/methods.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/methods.js +63 -11
- package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts +2 -1
- package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/orchestrator.js +60 -40
- package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts +6 -2
- package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/override-detection.js +49 -50
- package/dist/ir/converters/statements/declarations/classes/override-detection.js.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/properties.d.ts +9 -1
- package/dist/ir/converters/statements/declarations/classes/properties.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/classes/properties.js +119 -16
- package/dist/ir/converters/statements/declarations/classes/properties.js.map +1 -1
- package/dist/ir/converters/statements/declarations/enums.d.ts +2 -1
- package/dist/ir/converters/statements/declarations/enums.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/enums.js +8 -2
- package/dist/ir/converters/statements/declarations/enums.js.map +1 -1
- package/dist/ir/converters/statements/declarations/functions.d.ts +2 -1
- package/dist/ir/converters/statements/declarations/functions.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/functions.js +11 -6
- package/dist/ir/converters/statements/declarations/functions.js.map +1 -1
- package/dist/ir/converters/statements/declarations/index.d.ts +3 -1
- package/dist/ir/converters/statements/declarations/index.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/index.js +3 -1
- package/dist/ir/converters/statements/declarations/index.js.map +1 -1
- package/dist/ir/converters/statements/declarations/interfaces.d.ts +3 -2
- package/dist/ir/converters/statements/declarations/interfaces.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/interfaces.js +26 -20
- package/dist/ir/converters/statements/declarations/interfaces.js.map +1 -1
- package/dist/ir/converters/statements/declarations/registry.d.ts +72 -0
- package/dist/ir/converters/statements/declarations/registry.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/registry.js +92 -0
- package/dist/ir/converters/statements/declarations/registry.js.map +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.d.ts +2 -1
- package/dist/ir/converters/statements/declarations/type-aliases.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/type-aliases.js +6 -4
- package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.d.ts +11 -1
- package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations/variables.js +123 -19
- package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
- package/dist/ir/converters/statements/declarations.d.ts +4 -1
- package/dist/ir/converters/statements/declarations.d.ts.map +1 -1
- package/dist/ir/converters/statements/declarations.js +4 -1
- package/dist/ir/converters/statements/declarations.js.map +1 -1
- package/dist/ir/converters/statements/helpers.d.ts +4 -3
- package/dist/ir/converters/statements/helpers.d.ts.map +1 -1
- package/dist/ir/converters/statements/helpers.js +55 -31
- package/dist/ir/converters/statements/helpers.js.map +1 -1
- package/dist/ir/converters/statements/index.d.ts +1 -1
- package/dist/ir/converters/statements/index.d.ts.map +1 -1
- package/dist/ir/converters/statements/index.js +2 -1
- package/dist/ir/converters/statements/index.js.map +1 -1
- package/dist/ir/expression-converter.d.ts +10 -3
- package/dist/ir/expression-converter.d.ts.map +1 -1
- package/dist/ir/expression-converter.js +139 -57
- package/dist/ir/expression-converter.js.map +1 -1
- package/dist/ir/hierarchical-bindings-e2e.test.js +10 -6
- package/dist/ir/hierarchical-bindings-e2e.test.js.map +1 -1
- package/dist/ir/index.d.ts +5 -0
- package/dist/ir/index.d.ts.map +1 -1
- package/dist/ir/index.js +5 -0
- package/dist/ir/index.js.map +1 -1
- package/dist/ir/no-ts-type-inference.test.d.ts +17 -0
- package/dist/ir/no-ts-type-inference.test.d.ts.map +1 -0
- package/dist/ir/no-ts-type-inference.test.js +171 -0
- package/dist/ir/no-ts-type-inference.test.js.map +1 -0
- package/dist/ir/program-context.d.ts +87 -0
- package/dist/ir/program-context.d.ts.map +1 -0
- package/dist/ir/program-context.js +289 -0
- package/dist/ir/program-context.js.map +1 -0
- package/dist/ir/statement-converter.d.ts +14 -4
- package/dist/ir/statement-converter.d.ts.map +1 -1
- package/dist/ir/statement-converter.js +31 -21
- package/dist/ir/statement-converter.js.map +1 -1
- package/dist/ir/syntax/binding-patterns.d.ts +22 -0
- package/dist/ir/syntax/binding-patterns.d.ts.map +1 -0
- package/dist/ir/{type-converter/patterns.js → syntax/binding-patterns.js} +34 -8
- package/dist/ir/syntax/binding-patterns.js.map +1 -0
- package/dist/ir/thisarg-inference.test.d.ts +8 -0
- package/dist/ir/thisarg-inference.test.d.ts.map +1 -0
- package/dist/ir/thisarg-inference.test.js +94 -0
- package/dist/ir/thisarg-inference.test.js.map +1 -0
- package/dist/ir/type-system/index.d.ts +21 -0
- package/dist/ir/type-system/index.d.ts.map +1 -0
- package/dist/ir/type-system/index.js +43 -0
- package/dist/ir/type-system/index.js.map +1 -0
- package/dist/ir/type-system/internal/handle-types.d.ts +105 -0
- package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -0
- package/dist/ir/type-system/internal/handle-types.js +13 -0
- package/dist/ir/type-system/internal/handle-types.js.map +1 -0
- package/dist/ir/type-system/internal/nominal-env.d.ts +66 -0
- package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -0
- package/dist/ir/type-system/internal/nominal-env.js +301 -0
- package/dist/ir/type-system/internal/nominal-env.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/arrays.d.ts +11 -0
- package/dist/ir/type-system/internal/type-converter/arrays.d.ts.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/arrays.js +2 -2
- package/dist/ir/type-system/internal/type-converter/arrays.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/converter.d.ts +17 -0
- package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/converter.js +16 -0
- package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/functions.d.ts +14 -0
- package/dist/ir/type-system/internal/type-converter/functions.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/functions.js +66 -0
- package/dist/ir/type-system/internal/type-converter/functions.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/index.d.ts +11 -0
- package/dist/ir/type-system/internal/type-converter/index.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/index.js +11 -0
- package/dist/ir/type-system/internal/type-converter/index.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/inference.d.ts +37 -0
- package/dist/ir/type-system/internal/type-converter/inference.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/inference.js +32 -0
- package/dist/ir/type-system/internal/type-converter/inference.js.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.d.ts +1 -1
- package/dist/ir/type-system/internal/type-converter/literals.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/literals.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/objects.d.ts +20 -0
- package/dist/ir/type-system/internal/type-converter/objects.d.ts.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/objects.js +56 -6
- package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.d.ts +3 -2
- package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.js +63 -21
- package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.d.ts +4 -4
- package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.js +2 -2
- package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/references.d.ts +3 -2
- package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/references.js +545 -0
- package/dist/ir/type-system/internal/type-converter/references.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts +15 -0
- package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/unions-intersections.js +22 -0
- package/dist/ir/type-system/internal/type-converter/unions-intersections.js.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.d.ts +23 -36
- package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter/utility-types.js +879 -0
- package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter/utility-types.test.d.ts.map +1 -0
- package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.js +398 -120
- package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -0
- package/dist/ir/type-system/internal/type-converter.d.ts +9 -0
- package/dist/ir/type-system/internal/type-converter.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-converter.js +9 -0
- package/dist/ir/type-system/internal/type-converter.js.map +1 -0
- package/dist/ir/type-system/internal/type-registry.d.ts +112 -0
- package/dist/ir/type-system/internal/type-registry.d.ts.map +1 -0
- package/dist/ir/type-system/internal/type-registry.js +535 -0
- package/dist/ir/type-system/internal/type-registry.js.map +1 -0
- package/dist/ir/type-system/internal/universe/alias-table.d.ts +92 -0
- package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/alias-table.js +222 -0
- package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +44 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.js +1192 -0
- package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -0
- package/dist/ir/type-system/internal/universe/index.d.ts +26 -0
- package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/index.js +30 -0
- package/dist/ir/type-system/internal/universe/index.js.map +1 -0
- package/dist/ir/type-system/internal/universe/resolution.d.ts +115 -0
- package/dist/ir/type-system/internal/universe/resolution.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/resolution.js +181 -0
- package/dist/ir/type-system/internal/universe/resolution.js.map +1 -0
- package/dist/ir/type-system/internal/universe/source-catalog.d.ts +64 -0
- package/dist/ir/type-system/internal/universe/source-catalog.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/source-catalog.js +96 -0
- package/dist/ir/type-system/internal/universe/source-catalog.js.map +1 -0
- package/dist/ir/type-system/internal/universe/types.d.ts +436 -0
- package/dist/ir/type-system/internal/universe/types.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/types.js +69 -0
- package/dist/ir/type-system/internal/universe/types.js.map +1 -0
- package/dist/ir/type-system/internal/universe/unified-universe.d.ts +70 -0
- package/dist/ir/type-system/internal/universe/unified-universe.d.ts.map +1 -0
- package/dist/ir/type-system/internal/universe/unified-universe.js +319 -0
- package/dist/ir/type-system/internal/universe/unified-universe.js.map +1 -0
- package/dist/ir/type-system/type-system.d.ts +617 -0
- package/dist/ir/type-system/type-system.d.ts.map +1 -0
- package/dist/ir/type-system/type-system.js +2579 -0
- package/dist/ir/type-system/type-system.js.map +1 -0
- package/dist/ir/type-system/types.d.ts +176 -0
- package/dist/ir/type-system/types.d.ts.map +1 -0
- package/dist/ir/type-system/types.js +80 -0
- package/dist/ir/type-system/types.js.map +1 -0
- package/dist/ir/types/expressions.d.ts +35 -7
- package/dist/ir/types/expressions.d.ts.map +1 -1
- package/dist/ir/types/helpers.d.ts +22 -2
- package/dist/ir/types/helpers.d.ts.map +1 -1
- package/dist/ir/types/index.d.ts +4 -2
- 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.d.ts +144 -0
- package/dist/ir/types/ir-substitution.d.ts.map +1 -0
- package/dist/ir/types/ir-substitution.js +569 -0
- package/dist/ir/types/ir-substitution.js.map +1 -0
- package/dist/ir/types/ir-types.d.ts +10 -4
- package/dist/ir/types/ir-types.d.ts.map +1 -1
- package/dist/ir/types/numeric-helpers.d.ts +2 -1
- package/dist/ir/types/numeric-helpers.d.ts.map +1 -1
- package/dist/ir/types/numeric-helpers.js +9 -3
- package/dist/ir/types/numeric-helpers.js.map +1 -1
- package/dist/ir/types/statements.d.ts +22 -1
- package/dist/ir/types/statements.d.ts.map +1 -1
- package/dist/ir/types.d.ts +1 -1
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/types.js.map +1 -1
- package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
- package/dist/ir/validation/anonymous-type-lowering-pass.js +153 -8
- package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
- package/dist/ir/validation/arrow-return-finalization-pass.d.ts +28 -0
- package/dist/ir/validation/arrow-return-finalization-pass.d.ts.map +1 -0
- package/dist/ir/validation/arrow-return-finalization-pass.js +416 -0
- package/dist/ir/validation/arrow-return-finalization-pass.js.map +1 -0
- package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.js +40 -6
- package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
- package/dist/ir/validation/attribute-collection-pass.test.js +43 -36
- package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
- package/dist/ir/validation/char-validation-pass.d.ts +26 -0
- package/dist/ir/validation/char-validation-pass.d.ts.map +1 -0
- package/dist/ir/validation/char-validation-pass.js +495 -0
- package/dist/ir/validation/char-validation-pass.js.map +1 -0
- package/dist/ir/validation/index.d.ts +3 -0
- package/dist/ir/validation/index.d.ts.map +1 -1
- package/dist/ir/validation/index.js +3 -0
- package/dist/ir/validation/index.js.map +1 -1
- package/dist/ir/validation/numeric-coercion-pass.d.ts +22 -16
- package/dist/ir/validation/numeric-coercion-pass.d.ts.map +1 -1
- package/dist/ir/validation/numeric-coercion-pass.js +159 -51
- package/dist/ir/validation/numeric-coercion-pass.js.map +1 -1
- package/dist/ir/validation/numeric-invariants.test.js +72 -108
- package/dist/ir/validation/numeric-invariants.test.js.map +1 -1
- package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
- package/dist/ir/validation/numeric-proof-pass.js +71 -23
- package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
- package/dist/ir/validation/rest-type-synthesis-pass.d.ts +24 -0
- package/dist/ir/validation/rest-type-synthesis-pass.d.ts.map +1 -0
- package/dist/ir/validation/rest-type-synthesis-pass.js +417 -0
- package/dist/ir/validation/rest-type-synthesis-pass.js.map +1 -0
- package/dist/ir/validation/soundness-gate.d.ts +11 -1
- package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
- package/dist/ir/validation/soundness-gate.js +42 -10
- package/dist/ir/validation/soundness-gate.js.map +1 -1
- package/dist/ir/validation/soundness-gate.test.js +19 -2
- package/dist/ir/validation/soundness-gate.test.js.map +1 -1
- package/dist/ir/validation/virtual-marking-pass.d.ts +16 -0
- package/dist/ir/validation/virtual-marking-pass.d.ts.map +1 -0
- package/dist/ir/validation/virtual-marking-pass.js +77 -0
- package/dist/ir/validation/virtual-marking-pass.js.map +1 -0
- package/dist/ir/validation/yield-lowering-pass.test.js +2 -2
- package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
- package/dist/program/bindings.d.ts +44 -0
- package/dist/program/bindings.d.ts.map +1 -1
- package/dist/program/bindings.js +248 -2
- package/dist/program/bindings.js.map +1 -1
- package/dist/program/bindings.test.js +30 -0
- package/dist/program/bindings.test.js.map +1 -1
- package/dist/program/creation.d.ts.map +1 -1
- package/dist/program/creation.js +158 -4
- package/dist/program/creation.js.map +1 -1
- package/dist/program/dependency-graph.d.ts.map +1 -1
- package/dist/program/dependency-graph.js +33 -26
- package/dist/program/dependency-graph.js.map +1 -1
- package/dist/program/index.d.ts +1 -1
- package/dist/program/index.d.ts.map +1 -1
- package/dist/program/types.d.ts +7 -8
- package/dist/program/types.d.ts.map +1 -1
- package/dist/resolver/clr-bindings-resolver.d.ts +6 -0
- package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
- package/dist/resolver/clr-bindings-resolver.js +185 -39
- package/dist/resolver/clr-bindings-resolver.js.map +1 -1
- package/dist/resolver/clr-bindings-resolver.test.d.ts +2 -0
- package/dist/resolver/clr-bindings-resolver.test.d.ts.map +1 -0
- package/dist/resolver/clr-bindings-resolver.test.js +161 -0
- package/dist/resolver/clr-bindings-resolver.test.js.map +1 -0
- package/dist/resolver/import-resolution.d.ts +16 -1
- package/dist/resolver/import-resolution.d.ts.map +1 -1
- package/dist/resolver/import-resolution.js +29 -12
- package/dist/resolver/import-resolution.js.map +1 -1
- package/dist/resolver/namespace.d.ts +2 -1
- package/dist/resolver/namespace.d.ts.map +1 -1
- package/dist/resolver/namespace.js +5 -2
- package/dist/resolver/namespace.js.map +1 -1
- package/dist/resolver/namespace.test.js +6 -6
- package/dist/resolver/naming-policy.d.ts +20 -0
- package/dist/resolver/naming-policy.d.ts.map +1 -0
- package/dist/resolver/naming-policy.js +40 -0
- package/dist/resolver/naming-policy.js.map +1 -0
- package/dist/resolver/naming.d.ts +2 -5
- package/dist/resolver/naming.d.ts.map +1 -1
- package/dist/resolver/naming.js +3 -20
- package/dist/resolver/naming.js.map +1 -1
- package/dist/resolver.d.ts +2 -0
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +1 -0
- package/dist/resolver.js.map +1 -1
- package/dist/resolver.test.js +8 -3
- package/dist/resolver.test.js.map +1 -1
- package/dist/symbol-table/builder.d.ts +3 -1
- package/dist/symbol-table/builder.d.ts.map +1 -1
- package/dist/symbol-table/builder.js +9 -8
- package/dist/symbol-table/builder.js.map +1 -1
- package/dist/symbol-table/types.d.ts +2 -2
- package/dist/symbol-table/types.d.ts.map +1 -1
- package/dist/types/diagnostic.d.ts +12 -2
- package/dist/types/diagnostic.d.ts.map +1 -1
- package/dist/types/diagnostic.js +5 -1
- package/dist/types/diagnostic.js.map +1 -1
- package/dist/validation/core-intrinsics.d.ts +18 -0
- package/dist/validation/core-intrinsics.d.ts.map +1 -0
- package/dist/validation/core-intrinsics.js +186 -0
- package/dist/validation/core-intrinsics.js.map +1 -0
- package/dist/validation/extension-methods.d.ts +17 -0
- package/dist/validation/extension-methods.d.ts.map +1 -0
- package/dist/validation/extension-methods.js +133 -0
- package/dist/validation/extension-methods.js.map +1 -0
- package/dist/validation/generics.d.ts.map +1 -1
- package/dist/validation/generics.js +1 -129
- package/dist/validation/generics.js.map +1 -1
- package/dist/validation/imports.js +1 -1
- package/dist/validation/imports.js.map +1 -1
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +2 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/orchestrator.d.ts.map +1 -1
- package/dist/validation/orchestrator.js +4 -0
- package/dist/validation/orchestrator.js.map +1 -1
- package/dist/validation/static-safety.d.ts +1 -0
- package/dist/validation/static-safety.d.ts.map +1 -1
- package/dist/validation/static-safety.js +366 -96
- package/dist/validation/static-safety.js.map +1 -1
- package/dist/validator.test.js +123 -1
- package/dist/validator.test.js.map +1 -1
- package/package.json +2 -2
- package/dist/ir/type-converter/arrays.d.ts +0 -10
- package/dist/ir/type-converter/arrays.d.ts.map +0 -1
- package/dist/ir/type-converter/arrays.js.map +0 -1
- package/dist/ir/type-converter/converter.d.ts +0 -6
- package/dist/ir/type-converter/converter.d.ts.map +0 -1
- package/dist/ir/type-converter/converter.js +0 -6
- package/dist/ir/type-converter/converter.js.map +0 -1
- package/dist/ir/type-converter/functions.d.ts +0 -10
- package/dist/ir/type-converter/functions.d.ts.map +0 -1
- package/dist/ir/type-converter/functions.js +0 -15
- package/dist/ir/type-converter/functions.js.map +0 -1
- package/dist/ir/type-converter/index.d.ts +0 -7
- package/dist/ir/type-converter/index.d.ts.map +0 -1
- package/dist/ir/type-converter/index.js +0 -7
- package/dist/ir/type-converter/index.js.map +0 -1
- package/dist/ir/type-converter/inference.d.ts +0 -32
- package/dist/ir/type-converter/inference.d.ts.map +0 -1
- package/dist/ir/type-converter/inference.js +0 -297
- package/dist/ir/type-converter/inference.js.map +0 -1
- package/dist/ir/type-converter/literals.d.ts.map +0 -1
- package/dist/ir/type-converter/literals.js.map +0 -1
- package/dist/ir/type-converter/objects.d.ts +0 -16
- package/dist/ir/type-converter/objects.d.ts.map +0 -1
- package/dist/ir/type-converter/objects.js.map +0 -1
- package/dist/ir/type-converter/orchestrator.d.ts.map +0 -1
- package/dist/ir/type-converter/orchestrator.js.map +0 -1
- package/dist/ir/type-converter/patterns.d.ts +0 -10
- package/dist/ir/type-converter/patterns.d.ts.map +0 -1
- package/dist/ir/type-converter/patterns.js.map +0 -1
- package/dist/ir/type-converter/primitives.d.ts.map +0 -1
- package/dist/ir/type-converter/primitives.js.map +0 -1
- package/dist/ir/type-converter/references.d.ts.map +0 -1
- package/dist/ir/type-converter/references.js +0 -371
- package/dist/ir/type-converter/references.js.map +0 -1
- package/dist/ir/type-converter/unions-intersections.d.ts +0 -14
- package/dist/ir/type-converter/unions-intersections.d.ts.map +0 -1
- package/dist/ir/type-converter/unions-intersections.js +0 -22
- package/dist/ir/type-converter/unions-intersections.js.map +0 -1
- package/dist/ir/type-converter/utility-types.d.ts.map +0 -1
- package/dist/ir/type-converter/utility-types.js +0 -528
- package/dist/ir/type-converter/utility-types.js.map +0 -1
- package/dist/ir/type-converter/utility-types.test.d.ts.map +0 -1
- package/dist/ir/type-converter/utility-types.test.js.map +0 -1
- package/dist/ir/type-converter.d.ts +0 -6
- package/dist/ir/type-converter.d.ts.map +0 -1
- package/dist/ir/type-converter.js +0 -6
- package/dist/ir/type-converter.js.map +0 -1
- /package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.js +0 -0
- /package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.d.ts +0 -0
package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.js
RENAMED
|
@@ -10,6 +10,7 @@ import { describe, it } from "mocha";
|
|
|
10
10
|
import { expect } from "chai";
|
|
11
11
|
import * as ts from "typescript";
|
|
12
12
|
import { expandUtilityType, expandConditionalUtilityType, expandRecordType, } from "./utility-types.js";
|
|
13
|
+
import { createBinding } from "../../../binding/index.js";
|
|
13
14
|
/**
|
|
14
15
|
* Assert value is not null/undefined and return it typed as non-null.
|
|
15
16
|
* Throws if value is null or undefined.
|
|
@@ -45,7 +46,8 @@ const createTestProgram = (source, fileName = "test.ts") => {
|
|
|
45
46
|
const program = ts.createProgram([fileName], compilerOptions, host);
|
|
46
47
|
const sourceFile = assertDefined(program.getSourceFile(fileName), `Source file ${fileName} not found`);
|
|
47
48
|
const checker = program.getTypeChecker();
|
|
48
|
-
|
|
49
|
+
const binding = createBinding(checker);
|
|
50
|
+
return { program, checker, sourceFile, binding };
|
|
49
51
|
};
|
|
50
52
|
/**
|
|
51
53
|
* Helper to find a type alias by name and get its type reference node
|
|
@@ -66,7 +68,7 @@ const findTypeAliasReference = (sourceFile, aliasName) => {
|
|
|
66
68
|
/**
|
|
67
69
|
* Stub convertType for testing - just returns the type name
|
|
68
70
|
*/
|
|
69
|
-
const stubConvertType = (node,
|
|
71
|
+
const stubConvertType = (node, _binding) => {
|
|
70
72
|
if (ts.isTypeReferenceNode(node)) {
|
|
71
73
|
const name = ts.isIdentifier(node.typeName)
|
|
72
74
|
? node.typeName.text
|
|
@@ -79,13 +81,19 @@ const stubConvertType = (node, checker) => {
|
|
|
79
81
|
if (node.kind === ts.SyntaxKind.NumberKeyword) {
|
|
80
82
|
return { kind: "primitiveType", name: "number" };
|
|
81
83
|
}
|
|
84
|
+
if (node.kind === ts.SyntaxKind.BooleanKeyword) {
|
|
85
|
+
return { kind: "primitiveType", name: "boolean" };
|
|
86
|
+
}
|
|
82
87
|
if (node.kind === ts.SyntaxKind.UndefinedKeyword) {
|
|
83
88
|
return { kind: "primitiveType", name: "undefined" };
|
|
84
89
|
}
|
|
90
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) {
|
|
91
|
+
return { kind: "primitiveType", name: "null" };
|
|
92
|
+
}
|
|
85
93
|
if (node.kind === ts.SyntaxKind.NeverKeyword) {
|
|
86
94
|
return { kind: "neverType" };
|
|
87
95
|
}
|
|
88
|
-
// Handle literal type nodes (e.g., "a", 1)
|
|
96
|
+
// Handle literal type nodes (e.g., "a", 1, null, undefined)
|
|
89
97
|
if (ts.isLiteralTypeNode(node)) {
|
|
90
98
|
const literal = node.literal;
|
|
91
99
|
if (ts.isStringLiteral(literal)) {
|
|
@@ -94,11 +102,15 @@ const stubConvertType = (node, checker) => {
|
|
|
94
102
|
if (ts.isNumericLiteral(literal)) {
|
|
95
103
|
return { kind: "literalType", value: Number(literal.text) };
|
|
96
104
|
}
|
|
105
|
+
// null can appear as LiteralTypeNode in type positions
|
|
106
|
+
if (literal.kind === ts.SyntaxKind.NullKeyword) {
|
|
107
|
+
return { kind: "primitiveType", name: "null" };
|
|
108
|
+
}
|
|
97
109
|
}
|
|
98
110
|
if (ts.isUnionTypeNode(node)) {
|
|
99
111
|
return {
|
|
100
112
|
kind: "unionType",
|
|
101
|
-
types: node.types.map((t) => stubConvertType(t,
|
|
113
|
+
types: node.types.map((t) => stubConvertType(t, _binding)),
|
|
102
114
|
};
|
|
103
115
|
}
|
|
104
116
|
return { kind: "anyType" };
|
|
@@ -113,9 +125,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
113
125
|
}
|
|
114
126
|
type PartialWithIndex = Partial<WithStringIndex>;
|
|
115
127
|
`;
|
|
116
|
-
const {
|
|
128
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
117
129
|
const typeRef = findTypeAliasReference(sourceFile, "PartialWithIndex");
|
|
118
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
130
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
119
131
|
// Should return null because expansion would lose the index signature
|
|
120
132
|
expect(result).to.equal(null);
|
|
121
133
|
});
|
|
@@ -127,9 +139,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
127
139
|
}
|
|
128
140
|
type ReadonlyWithIndex = Readonly<WithNumberIndex>;
|
|
129
141
|
`;
|
|
130
|
-
const {
|
|
142
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
131
143
|
const typeRef = findTypeAliasReference(sourceFile, "ReadonlyWithIndex");
|
|
132
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly",
|
|
144
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly", binding, stubConvertType);
|
|
133
145
|
// Should return null because expansion would lose the index signature
|
|
134
146
|
expect(result).to.equal(null);
|
|
135
147
|
});
|
|
@@ -141,9 +153,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
141
153
|
}
|
|
142
154
|
type PartialPerson = Partial<Person>;
|
|
143
155
|
`;
|
|
144
|
-
const {
|
|
156
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
145
157
|
const typeRef = findTypeAliasReference(sourceFile, "PartialPerson");
|
|
146
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
158
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
147
159
|
// Should expand successfully
|
|
148
160
|
expect(result).not.to.equal(null);
|
|
149
161
|
expect(result?.kind).to.equal("objectType");
|
|
@@ -162,11 +174,11 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
162
174
|
}
|
|
163
175
|
type PartialWithSymbol = Partial<WithSymbol>;
|
|
164
176
|
`;
|
|
165
|
-
const {
|
|
177
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
166
178
|
const typeRef = findTypeAliasReference(sourceFile, "PartialWithSymbol");
|
|
167
179
|
// This may or may not find the type ref depending on how TS handles it
|
|
168
180
|
if (typeRef) {
|
|
169
|
-
const result = expandUtilityType(typeRef, "Partial",
|
|
181
|
+
const result = expandUtilityType(typeRef, "Partial", binding, stubConvertType);
|
|
170
182
|
// If expansion proceeds, it should return null due to symbol key
|
|
171
183
|
// (symbol keys start with __@ internally)
|
|
172
184
|
// Note: The actual behavior depends on whether TS resolves the symbol key
|
|
@@ -184,9 +196,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
184
196
|
}
|
|
185
197
|
type PartialWithUndefined = Partial<WithExplicitUndefined>;
|
|
186
198
|
`;
|
|
187
|
-
const {
|
|
199
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
188
200
|
const typeRef = findTypeAliasReference(sourceFile, "PartialWithUndefined");
|
|
189
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
201
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
190
202
|
expect(result).not.to.equal(null);
|
|
191
203
|
expect(result?.kind).to.equal("objectType");
|
|
192
204
|
// The property should preserve the union with undefined
|
|
@@ -207,9 +219,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
207
219
|
}
|
|
208
220
|
type PartialWithSynthetic = Partial<WithSyntheticUndefined>;
|
|
209
221
|
`;
|
|
210
|
-
const {
|
|
222
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
211
223
|
const typeRef = findTypeAliasReference(sourceFile, "PartialWithSynthetic");
|
|
212
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
224
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
213
225
|
expect(result).not.to.equal(null);
|
|
214
226
|
expect(result?.kind).to.equal("objectType");
|
|
215
227
|
// The property type should be string (not string | undefined)
|
|
@@ -231,9 +243,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
231
243
|
}
|
|
232
244
|
type PartialRequired = Partial<WithRequiredUndefined>;
|
|
233
245
|
`;
|
|
234
|
-
const {
|
|
246
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
235
247
|
const typeRef = findTypeAliasReference(sourceFile, "PartialRequired");
|
|
236
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
248
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
237
249
|
expect(result).not.to.equal(null);
|
|
238
250
|
const xProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "x");
|
|
239
251
|
expect(xProp).not.to.equal(undefined);
|
|
@@ -252,9 +264,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
252
264
|
}
|
|
253
265
|
type PartialReadonly = Partial<Readonly<Person>>;
|
|
254
266
|
`;
|
|
255
|
-
const {
|
|
267
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
256
268
|
const typeRef = findTypeAliasReference(sourceFile, "PartialReadonly");
|
|
257
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
269
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
258
270
|
expect(result).not.to.equal(null);
|
|
259
271
|
expect(result?.kind).to.equal("objectType");
|
|
260
272
|
// All properties should be readonly (from inner Readonly<T>)
|
|
@@ -273,9 +285,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
273
285
|
}
|
|
274
286
|
type ReadonlyPartial = Readonly<Partial<Person>>;
|
|
275
287
|
`;
|
|
276
|
-
const {
|
|
288
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
277
289
|
const typeRef = findTypeAliasReference(sourceFile, "ReadonlyPartial");
|
|
278
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly",
|
|
290
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly", binding, stubConvertType);
|
|
279
291
|
expect(result).not.to.equal(null);
|
|
280
292
|
expect(result?.kind).to.equal("objectType");
|
|
281
293
|
// All properties should be both readonly (from Readonly<T>) and optional (from Partial<T>)
|
|
@@ -296,9 +308,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
296
308
|
}
|
|
297
309
|
type PartialWithMethod = Partial<WithMethod>;
|
|
298
310
|
`;
|
|
299
|
-
const {
|
|
311
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
300
312
|
const typeRef = findTypeAliasReference(sourceFile, "PartialWithMethod");
|
|
301
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
313
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
302
314
|
expect(result).not.to.equal(null);
|
|
303
315
|
expect(result?.kind).to.equal("objectType");
|
|
304
316
|
// Should have both property and method
|
|
@@ -323,9 +335,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
323
335
|
}
|
|
324
336
|
type ContactInfo = Pick<Person, "name" | "email" | "phone">;
|
|
325
337
|
`;
|
|
326
|
-
const {
|
|
338
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
327
339
|
const typeRef = findTypeAliasReference(sourceFile, "ContactInfo");
|
|
328
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Pick",
|
|
340
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Pick", binding, stubConvertType);
|
|
329
341
|
expect(result).not.to.equal(null);
|
|
330
342
|
expect(result?.kind).to.equal("objectType");
|
|
331
343
|
// Should only have name, email, phone (not age)
|
|
@@ -348,9 +360,9 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
348
360
|
}
|
|
349
361
|
type MinimalPerson = Omit<Person, "email" | "phone">;
|
|
350
362
|
`;
|
|
351
|
-
const {
|
|
363
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
352
364
|
const typeRef = findTypeAliasReference(sourceFile, "MinimalPerson");
|
|
353
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Omit",
|
|
365
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Omit", binding, stubConvertType);
|
|
354
366
|
expect(result).not.to.equal(null);
|
|
355
367
|
expect(result?.kind).to.equal("objectType");
|
|
356
368
|
// Should only have name, age (not email, phone)
|
|
@@ -369,7 +381,7 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
369
381
|
const source = `
|
|
370
382
|
function process<T>(data: Partial<T>): void {}
|
|
371
383
|
`;
|
|
372
|
-
const {
|
|
384
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
373
385
|
// Find the Partial<T> type reference in the function parameter
|
|
374
386
|
let typeRef = null;
|
|
375
387
|
const visitor = (node) => {
|
|
@@ -381,11 +393,255 @@ describe("Utility Type Expansion Safety", () => {
|
|
|
381
393
|
ts.forEachChild(node, visitor);
|
|
382
394
|
};
|
|
383
395
|
ts.forEachChild(sourceFile, visitor);
|
|
384
|
-
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial",
|
|
396
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
385
397
|
// Should return null because T is a type parameter - can't expand at compile time
|
|
386
398
|
expect(result).to.equal(null);
|
|
387
399
|
});
|
|
388
400
|
});
|
|
401
|
+
describe("Comprehensive utility type tests (nested, recursive, generic)", () => {
|
|
402
|
+
it("should expand Partial on recursive type (tree node)", () => {
|
|
403
|
+
const source = `
|
|
404
|
+
interface TreeNode {
|
|
405
|
+
value: number;
|
|
406
|
+
children: TreeNode[];
|
|
407
|
+
}
|
|
408
|
+
type PartialTreeNode = Partial<TreeNode>;
|
|
409
|
+
`;
|
|
410
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
411
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialTreeNode");
|
|
412
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
413
|
+
expect(result).not.to.equal(null);
|
|
414
|
+
expect(result?.kind).to.equal("objectType");
|
|
415
|
+
expect(result?.members).to.have.length(2);
|
|
416
|
+
const valueProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "value");
|
|
417
|
+
const childrenProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "children");
|
|
418
|
+
expect(valueProp).not.to.equal(undefined);
|
|
419
|
+
expect(childrenProp).not.to.equal(undefined);
|
|
420
|
+
if (valueProp && valueProp.kind === "propertySignature") {
|
|
421
|
+
expect(valueProp.isOptional).to.equal(true);
|
|
422
|
+
}
|
|
423
|
+
if (childrenProp && childrenProp.kind === "propertySignature") {
|
|
424
|
+
expect(childrenProp.isOptional).to.equal(true);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
it("should expand Partial on linked list type (self-referential)", () => {
|
|
428
|
+
const source = `
|
|
429
|
+
interface ListNode<T> {
|
|
430
|
+
value: T;
|
|
431
|
+
next: ListNode<T> | null;
|
|
432
|
+
}
|
|
433
|
+
type PartialListNode = Partial<ListNode<string>>;
|
|
434
|
+
`;
|
|
435
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
436
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialListNode");
|
|
437
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
438
|
+
expect(result).not.to.equal(null);
|
|
439
|
+
expect(result?.kind).to.equal("objectType");
|
|
440
|
+
const valueProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "value");
|
|
441
|
+
const nextProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "next");
|
|
442
|
+
expect(valueProp).not.to.equal(undefined);
|
|
443
|
+
expect(nextProp).not.to.equal(undefined);
|
|
444
|
+
});
|
|
445
|
+
it("should expand triple-nested utility types", () => {
|
|
446
|
+
const source = `
|
|
447
|
+
interface Data {
|
|
448
|
+
id: number;
|
|
449
|
+
name: string;
|
|
450
|
+
}
|
|
451
|
+
type TripleNested = Partial<Readonly<Required<Data>>>;
|
|
452
|
+
`;
|
|
453
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
454
|
+
const typeRef = findTypeAliasReference(sourceFile, "TripleNested");
|
|
455
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
456
|
+
expect(result).not.to.equal(null);
|
|
457
|
+
expect(result?.kind).to.equal("objectType");
|
|
458
|
+
const idProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "id");
|
|
459
|
+
expect(idProp).not.to.equal(undefined);
|
|
460
|
+
if (idProp && idProp.kind === "propertySignature") {
|
|
461
|
+
expect(idProp.isReadonly).to.equal(true);
|
|
462
|
+
expect(idProp.isOptional).to.equal(true);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
it("should expand Pick on nested utility type", () => {
|
|
466
|
+
const source = `
|
|
467
|
+
interface User {
|
|
468
|
+
id: number;
|
|
469
|
+
name: string;
|
|
470
|
+
email: string;
|
|
471
|
+
password: string;
|
|
472
|
+
}
|
|
473
|
+
type SafeUser = Pick<Readonly<User>, "id" | "name" | "email">;
|
|
474
|
+
`;
|
|
475
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
476
|
+
const typeRef = findTypeAliasReference(sourceFile, "SafeUser");
|
|
477
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Pick", binding, stubConvertType);
|
|
478
|
+
expect(result).not.to.equal(null);
|
|
479
|
+
expect(result?.kind).to.equal("objectType");
|
|
480
|
+
expect(result?.members).to.have.length(3);
|
|
481
|
+
const propNames = result?.members
|
|
482
|
+
.filter((m) => m.kind === "propertySignature")
|
|
483
|
+
.map((m) => m.name);
|
|
484
|
+
expect(propNames).to.include("id");
|
|
485
|
+
expect(propNames).to.include("name");
|
|
486
|
+
expect(propNames).to.include("email");
|
|
487
|
+
expect(propNames).not.to.include("password");
|
|
488
|
+
});
|
|
489
|
+
it("should expand Omit on Partial type", () => {
|
|
490
|
+
const source = `
|
|
491
|
+
interface Config {
|
|
492
|
+
host: string;
|
|
493
|
+
port: number;
|
|
494
|
+
timeout: number;
|
|
495
|
+
debug: boolean;
|
|
496
|
+
}
|
|
497
|
+
type PartialConfig = Omit<Partial<Config>, "debug">;
|
|
498
|
+
`;
|
|
499
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
500
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialConfig");
|
|
501
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Omit", binding, stubConvertType);
|
|
502
|
+
expect(result).not.to.equal(null);
|
|
503
|
+
expect(result?.kind).to.equal("objectType");
|
|
504
|
+
expect(result?.members).to.have.length(3);
|
|
505
|
+
const propNames = result?.members
|
|
506
|
+
.filter((m) => m.kind === "propertySignature")
|
|
507
|
+
.map((m) => m.name);
|
|
508
|
+
expect(propNames).not.to.include("debug");
|
|
509
|
+
expect(propNames).to.include("host");
|
|
510
|
+
});
|
|
511
|
+
it("should expand Required on Partial type (roundtrip)", () => {
|
|
512
|
+
const source = `
|
|
513
|
+
interface Base {
|
|
514
|
+
x: number;
|
|
515
|
+
y: number;
|
|
516
|
+
}
|
|
517
|
+
type RoundTrip = Required<Partial<Base>>;
|
|
518
|
+
`;
|
|
519
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
520
|
+
const typeRef = findTypeAliasReference(sourceFile, "RoundTrip");
|
|
521
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Required", binding, stubConvertType);
|
|
522
|
+
expect(result).not.to.equal(null);
|
|
523
|
+
expect(result?.kind).to.equal("objectType");
|
|
524
|
+
const xProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "x");
|
|
525
|
+
expect(xProp).not.to.equal(undefined);
|
|
526
|
+
if (xProp && xProp.kind === "propertySignature") {
|
|
527
|
+
// Required removes optional, so isOptional should be false
|
|
528
|
+
expect(xProp.isOptional).to.equal(false);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
it("should expand utility type on generic interface with concrete type arg", () => {
|
|
532
|
+
const source = `
|
|
533
|
+
interface Container<T> {
|
|
534
|
+
value: T;
|
|
535
|
+
metadata: string;
|
|
536
|
+
}
|
|
537
|
+
type PartialNumberContainer = Partial<Container<number>>;
|
|
538
|
+
`;
|
|
539
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
540
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialNumberContainer");
|
|
541
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
542
|
+
expect(result).not.to.equal(null);
|
|
543
|
+
expect(result?.kind).to.equal("objectType");
|
|
544
|
+
const valueProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "value");
|
|
545
|
+
const metadataProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "metadata");
|
|
546
|
+
expect(valueProp).not.to.equal(undefined);
|
|
547
|
+
expect(metadataProp).not.to.equal(undefined);
|
|
548
|
+
if (valueProp && valueProp.kind === "propertySignature") {
|
|
549
|
+
expect(valueProp.isOptional).to.equal(true);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
it("should expand utility type on generic interface with multiple type params", () => {
|
|
553
|
+
const source = `
|
|
554
|
+
interface Pair<K, V> {
|
|
555
|
+
key: K;
|
|
556
|
+
value: V;
|
|
557
|
+
}
|
|
558
|
+
type PartialPair = Partial<Pair<string, number>>;
|
|
559
|
+
`;
|
|
560
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
561
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialPair");
|
|
562
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
563
|
+
expect(result).not.to.equal(null);
|
|
564
|
+
expect(result?.kind).to.equal("objectType");
|
|
565
|
+
expect(result?.members).to.have.length(2);
|
|
566
|
+
// Verify both properties exist and are optional
|
|
567
|
+
const keyProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "key");
|
|
568
|
+
const valueProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "value");
|
|
569
|
+
expect(keyProp).not.to.equal(undefined);
|
|
570
|
+
expect(valueProp).not.to.equal(undefined);
|
|
571
|
+
if (keyProp && keyProp.kind === "propertySignature") {
|
|
572
|
+
expect(keyProp.isOptional).to.equal(true);
|
|
573
|
+
}
|
|
574
|
+
if (valueProp && valueProp.kind === "propertySignature") {
|
|
575
|
+
expect(valueProp.isOptional).to.equal(true);
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
it("should expand Readonly on interface with method returning self type", () => {
|
|
579
|
+
const source = `
|
|
580
|
+
interface Builder {
|
|
581
|
+
value: number;
|
|
582
|
+
build(): Builder;
|
|
583
|
+
}
|
|
584
|
+
type ReadonlyBuilder = Readonly<Builder>;
|
|
585
|
+
`;
|
|
586
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
587
|
+
const typeRef = findTypeAliasReference(sourceFile, "ReadonlyBuilder");
|
|
588
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly", binding, stubConvertType);
|
|
589
|
+
expect(result).not.to.equal(null);
|
|
590
|
+
expect(result?.kind).to.equal("objectType");
|
|
591
|
+
const valueProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "value");
|
|
592
|
+
const buildMethod = result?.members.find((m) => m.kind === "methodSignature" && m.name === "build");
|
|
593
|
+
expect(valueProp).not.to.equal(undefined);
|
|
594
|
+
expect(buildMethod).not.to.equal(undefined);
|
|
595
|
+
if (valueProp && valueProp.kind === "propertySignature") {
|
|
596
|
+
expect(valueProp.isReadonly).to.equal(true);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
it("should expand utility type on deeply nested object type", () => {
|
|
600
|
+
const source = `
|
|
601
|
+
interface DeepNested {
|
|
602
|
+
level1: {
|
|
603
|
+
level2: {
|
|
604
|
+
level3: {
|
|
605
|
+
value: string;
|
|
606
|
+
};
|
|
607
|
+
};
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
type PartialDeep = Partial<DeepNested>;
|
|
611
|
+
`;
|
|
612
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
613
|
+
const typeRef = findTypeAliasReference(sourceFile, "PartialDeep");
|
|
614
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", binding, stubConvertType);
|
|
615
|
+
expect(result).not.to.equal(null);
|
|
616
|
+
expect(result?.kind).to.equal("objectType");
|
|
617
|
+
const level1Prop = result?.members.find((m) => m.kind === "propertySignature" && m.name === "level1");
|
|
618
|
+
expect(level1Prop).not.to.equal(undefined);
|
|
619
|
+
if (level1Prop && level1Prop.kind === "propertySignature") {
|
|
620
|
+
expect(level1Prop.isOptional).to.equal(true);
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
it("should handle Pick with single key on large interface", () => {
|
|
624
|
+
const source = `
|
|
625
|
+
interface LargeInterface {
|
|
626
|
+
a: string;
|
|
627
|
+
b: number;
|
|
628
|
+
c: boolean;
|
|
629
|
+
d: string[];
|
|
630
|
+
e: number[];
|
|
631
|
+
f: { nested: string };
|
|
632
|
+
}
|
|
633
|
+
type SinglePick = Pick<LargeInterface, "c">;
|
|
634
|
+
`;
|
|
635
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
636
|
+
const typeRef = findTypeAliasReference(sourceFile, "SinglePick");
|
|
637
|
+
const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Pick", binding, stubConvertType);
|
|
638
|
+
expect(result).not.to.equal(null);
|
|
639
|
+
expect(result?.kind).to.equal("objectType");
|
|
640
|
+
expect(result?.members).to.have.length(1);
|
|
641
|
+
const cProp = result?.members.find((m) => m.kind === "propertySignature" && m.name === "c");
|
|
642
|
+
expect(cProp).not.to.equal(undefined);
|
|
643
|
+
});
|
|
644
|
+
});
|
|
389
645
|
});
|
|
390
646
|
describe("Conditional Utility Type Expansion", () => {
|
|
391
647
|
describe("NonNullable<T>", () => {
|
|
@@ -393,9 +649,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
393
649
|
const source = `
|
|
394
650
|
type Result = NonNullable<string | null>;
|
|
395
651
|
`;
|
|
396
|
-
const {
|
|
652
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
397
653
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
398
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
654
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
399
655
|
expect(result).not.to.equal(null);
|
|
400
656
|
expect(result?.kind).to.equal("primitiveType");
|
|
401
657
|
if (result?.kind === "primitiveType") {
|
|
@@ -406,9 +662,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
406
662
|
const source = `
|
|
407
663
|
type Result = NonNullable<string | null | undefined>;
|
|
408
664
|
`;
|
|
409
|
-
const {
|
|
665
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
410
666
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
411
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
667
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
412
668
|
expect(result).not.to.equal(null);
|
|
413
669
|
expect(result?.kind).to.equal("primitiveType");
|
|
414
670
|
if (result?.kind === "primitiveType") {
|
|
@@ -419,9 +675,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
419
675
|
const source = `
|
|
420
676
|
type Result = NonNullable<null | undefined>;
|
|
421
677
|
`;
|
|
422
|
-
const {
|
|
678
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
423
679
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
424
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
680
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
425
681
|
expect(result).not.to.equal(null);
|
|
426
682
|
expect(result?.kind).to.equal("neverType");
|
|
427
683
|
});
|
|
@@ -429,9 +685,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
429
685
|
const source = `
|
|
430
686
|
type Result = NonNullable<any>;
|
|
431
687
|
`;
|
|
432
|
-
const {
|
|
688
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
433
689
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
434
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
690
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
435
691
|
expect(result).not.to.equal(null);
|
|
436
692
|
expect(result?.kind).to.equal("anyType");
|
|
437
693
|
});
|
|
@@ -439,9 +695,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
439
695
|
const source = `
|
|
440
696
|
type Result = NonNullable<unknown>;
|
|
441
697
|
`;
|
|
442
|
-
const {
|
|
698
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
443
699
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
444
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
700
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
445
701
|
expect(result).not.to.equal(null);
|
|
446
702
|
expect(result?.kind).to.equal("unknownType");
|
|
447
703
|
});
|
|
@@ -449,7 +705,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
449
705
|
const source = `
|
|
450
706
|
function process<T>(data: NonNullable<T>): void {}
|
|
451
707
|
`;
|
|
452
|
-
const {
|
|
708
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
453
709
|
let typeRef = null;
|
|
454
710
|
const visitor = (node) => {
|
|
455
711
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -460,7 +716,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
460
716
|
ts.forEachChild(node, visitor);
|
|
461
717
|
};
|
|
462
718
|
ts.forEachChild(sourceFile, visitor);
|
|
463
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable",
|
|
719
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", binding, stubConvertType);
|
|
464
720
|
expect(result).to.equal(null);
|
|
465
721
|
});
|
|
466
722
|
});
|
|
@@ -469,9 +725,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
469
725
|
const source = `
|
|
470
726
|
type Result = Exclude<"a" | "b" | "c", "a">;
|
|
471
727
|
`;
|
|
472
|
-
const {
|
|
728
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
473
729
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
474
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
730
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
475
731
|
// Should expand successfully (result is "b" | "c")
|
|
476
732
|
// Note: The exact IR kind depends on how TypeScript represents the resolved type
|
|
477
733
|
// which may vary. The key is that expansion succeeds and doesn't return null.
|
|
@@ -481,9 +737,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
481
737
|
const source = `
|
|
482
738
|
type Result = Exclude<string | number, number>;
|
|
483
739
|
`;
|
|
484
|
-
const {
|
|
740
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
485
741
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
486
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
742
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
487
743
|
expect(result).not.to.equal(null);
|
|
488
744
|
expect(result?.kind).to.equal("primitiveType");
|
|
489
745
|
if (result?.kind === "primitiveType") {
|
|
@@ -494,9 +750,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
494
750
|
const source = `
|
|
495
751
|
type Result = Exclude<string, string>;
|
|
496
752
|
`;
|
|
497
|
-
const {
|
|
753
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
498
754
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
499
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
755
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
500
756
|
expect(result).not.to.equal(null);
|
|
501
757
|
expect(result?.kind).to.equal("neverType");
|
|
502
758
|
});
|
|
@@ -504,7 +760,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
504
760
|
const source = `
|
|
505
761
|
function process<T>(data: Exclude<T, null>): void {}
|
|
506
762
|
`;
|
|
507
|
-
const {
|
|
763
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
508
764
|
let typeRef = null;
|
|
509
765
|
const visitor = (node) => {
|
|
510
766
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -515,7 +771,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
515
771
|
ts.forEachChild(node, visitor);
|
|
516
772
|
};
|
|
517
773
|
ts.forEachChild(sourceFile, visitor);
|
|
518
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
774
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
519
775
|
expect(result).to.equal(null);
|
|
520
776
|
});
|
|
521
777
|
});
|
|
@@ -524,9 +780,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
524
780
|
const source = `
|
|
525
781
|
type Result = Extract<"a" | "b" | "c", "a" | "f">;
|
|
526
782
|
`;
|
|
527
|
-
const {
|
|
783
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
528
784
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
529
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
785
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
530
786
|
expect(result).not.to.equal(null);
|
|
531
787
|
// Result should be "a" (the only common literal)
|
|
532
788
|
});
|
|
@@ -534,9 +790,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
534
790
|
const source = `
|
|
535
791
|
type Result = Extract<string | number, string>;
|
|
536
792
|
`;
|
|
537
|
-
const {
|
|
793
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
538
794
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
539
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
795
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
540
796
|
expect(result).not.to.equal(null);
|
|
541
797
|
expect(result?.kind).to.equal("primitiveType");
|
|
542
798
|
if (result?.kind === "primitiveType") {
|
|
@@ -547,9 +803,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
547
803
|
const source = `
|
|
548
804
|
type Result = Extract<string, number>;
|
|
549
805
|
`;
|
|
550
|
-
const {
|
|
806
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
551
807
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
552
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
808
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
553
809
|
expect(result).not.to.equal(null);
|
|
554
810
|
expect(result?.kind).to.equal("neverType");
|
|
555
811
|
});
|
|
@@ -559,9 +815,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
559
815
|
const source = `
|
|
560
816
|
type Result = Exclude<never, string>;
|
|
561
817
|
`;
|
|
562
|
-
const {
|
|
818
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
563
819
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
564
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
820
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
565
821
|
expect(result).not.to.equal(null);
|
|
566
822
|
expect(result?.kind).to.equal("neverType");
|
|
567
823
|
});
|
|
@@ -569,9 +825,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
569
825
|
const source = `
|
|
570
826
|
type Result = Extract<never, string>;
|
|
571
827
|
`;
|
|
572
|
-
const {
|
|
828
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
573
829
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
574
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
830
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
575
831
|
expect(result).not.to.equal(null);
|
|
576
832
|
expect(result?.kind).to.equal("neverType");
|
|
577
833
|
});
|
|
@@ -579,9 +835,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
579
835
|
const source = `
|
|
580
836
|
type Result = Exclude<"a" | "b" | "c" | "d", "a" | "c">;
|
|
581
837
|
`;
|
|
582
|
-
const {
|
|
838
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
583
839
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
584
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
840
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
585
841
|
expect(result).not.to.equal(null);
|
|
586
842
|
// Should be a union of "b" | "d" (TypeScript checker resolves this)
|
|
587
843
|
});
|
|
@@ -589,9 +845,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
589
845
|
const source = `
|
|
590
846
|
type Result = Extract<"a" | "b" | "c" | "d", "a" | "c" | "e">;
|
|
591
847
|
`;
|
|
592
|
-
const {
|
|
848
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
593
849
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
594
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
850
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
595
851
|
expect(result).not.to.equal(null);
|
|
596
852
|
// Should be a union of "a" | "c" (TypeScript checker resolves this)
|
|
597
853
|
});
|
|
@@ -599,9 +855,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
599
855
|
const source = `
|
|
600
856
|
type Result = Exclude<string | number | (() => void), Function>;
|
|
601
857
|
`;
|
|
602
|
-
const {
|
|
858
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
603
859
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
604
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
860
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
605
861
|
expect(result).not.to.equal(null);
|
|
606
862
|
// Should expand to string | number (function removed)
|
|
607
863
|
});
|
|
@@ -611,13 +867,20 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
611
867
|
type Mixed = ("a" | "b") | (1 | 2);
|
|
612
868
|
type OnlyNumbers = Exclude<Mixed, string>;
|
|
613
869
|
`;
|
|
614
|
-
const {
|
|
870
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
615
871
|
const typeRef = findTypeAliasReference(sourceFile, "OnlyNumbers");
|
|
616
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
872
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
617
873
|
expect(result).not.to.equal(null);
|
|
618
874
|
// Should be 1 | 2 (string literals removed)
|
|
619
875
|
// TypeScript distributes over the union and removes string-assignable types
|
|
620
876
|
expect(result?.kind).to.equal("unionType");
|
|
877
|
+
if (result?.kind === "unionType") {
|
|
878
|
+
expect(result.types).to.have.length(2);
|
|
879
|
+
const values = result.types
|
|
880
|
+
.filter((t) => t.kind === "literalType")
|
|
881
|
+
.map((t) => (t.kind === "literalType" ? t.value : null));
|
|
882
|
+
expect(values).to.deep.equal([1, 2]);
|
|
883
|
+
}
|
|
621
884
|
});
|
|
622
885
|
it("should distribute Extract over mixed string and number literals", () => {
|
|
623
886
|
// Alice's review case: mixed literals with Extract filtering by type
|
|
@@ -625,21 +888,28 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
625
888
|
type Mixed = ("a" | "b") | (1 | 2);
|
|
626
889
|
type OnlyStrings = Extract<Mixed, string>;
|
|
627
890
|
`;
|
|
628
|
-
const {
|
|
891
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
629
892
|
const typeRef = findTypeAliasReference(sourceFile, "OnlyStrings");
|
|
630
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract",
|
|
893
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", binding, stubConvertType);
|
|
631
894
|
expect(result).not.to.equal(null);
|
|
632
895
|
// Should be "a" | "b" (number literals removed)
|
|
633
896
|
// TypeScript distributes over the union and keeps only string-assignable types
|
|
634
897
|
expect(result?.kind).to.equal("unionType");
|
|
898
|
+
if (result?.kind === "unionType") {
|
|
899
|
+
expect(result.types).to.have.length(2);
|
|
900
|
+
const values = result.types
|
|
901
|
+
.filter((t) => t.kind === "literalType")
|
|
902
|
+
.map((t) => (t.kind === "literalType" ? t.value : null));
|
|
903
|
+
expect(values).to.deep.equal(["a", "b"]);
|
|
904
|
+
}
|
|
635
905
|
});
|
|
636
906
|
it("should handle nested conditional types", () => {
|
|
637
907
|
const source = `
|
|
638
908
|
type Result = Exclude<Exclude<string | null | undefined, null>, undefined>;
|
|
639
909
|
`;
|
|
640
|
-
const {
|
|
910
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
641
911
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
642
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude",
|
|
912
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", binding, stubConvertType);
|
|
643
913
|
expect(result).not.to.equal(null);
|
|
644
914
|
expect(result?.kind).to.equal("primitiveType");
|
|
645
915
|
if (result?.kind === "primitiveType") {
|
|
@@ -652,9 +922,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
652
922
|
const source = `
|
|
653
923
|
type Result = ReturnType<() => string>;
|
|
654
924
|
`;
|
|
655
|
-
const {
|
|
925
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
656
926
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
657
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
927
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
658
928
|
expect(result).not.to.equal(null);
|
|
659
929
|
expect(result?.kind).to.equal("primitiveType");
|
|
660
930
|
if (result?.kind === "primitiveType") {
|
|
@@ -665,9 +935,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
665
935
|
const source = `
|
|
666
936
|
type Result = ReturnType<(x: number) => boolean>;
|
|
667
937
|
`;
|
|
668
|
-
const {
|
|
938
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
669
939
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
670
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
940
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
671
941
|
expect(result).not.to.equal(null);
|
|
672
942
|
expect(result?.kind).to.equal("primitiveType");
|
|
673
943
|
if (result?.kind === "primitiveType") {
|
|
@@ -678,9 +948,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
678
948
|
const source = `
|
|
679
949
|
type Result = ReturnType<() => void>;
|
|
680
950
|
`;
|
|
681
|
-
const {
|
|
951
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
682
952
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
683
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
953
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
684
954
|
expect(result).not.to.equal(null);
|
|
685
955
|
// void is handled by fallback
|
|
686
956
|
});
|
|
@@ -690,12 +960,19 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
690
960
|
type Fn2 = () => number;
|
|
691
961
|
type Result = ReturnType<Fn1 | Fn2>;
|
|
692
962
|
`;
|
|
693
|
-
const {
|
|
963
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
694
964
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
695
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
965
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
696
966
|
expect(result).not.to.equal(null);
|
|
697
967
|
// Should be string | number
|
|
698
968
|
expect(result?.kind).to.equal("unionType");
|
|
969
|
+
if (result?.kind === "unionType") {
|
|
970
|
+
expect(result.types).to.have.length(2);
|
|
971
|
+
const names = result.types
|
|
972
|
+
.filter((t) => t.kind === "primitiveType")
|
|
973
|
+
.map((t) => (t.kind === "primitiveType" ? t.name : null));
|
|
974
|
+
expect(names).to.deep.equal(["string", "number"]);
|
|
975
|
+
}
|
|
699
976
|
});
|
|
700
977
|
it("should return null for ReturnType<T> where T is a type parameter", () => {
|
|
701
978
|
const source = `
|
|
@@ -703,7 +980,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
703
980
|
return fn();
|
|
704
981
|
}
|
|
705
982
|
`;
|
|
706
|
-
const {
|
|
983
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
707
984
|
let typeRef = null;
|
|
708
985
|
const visitor = (node) => {
|
|
709
986
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -714,7 +991,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
714
991
|
ts.forEachChild(node, visitor);
|
|
715
992
|
};
|
|
716
993
|
ts.forEachChild(sourceFile, visitor);
|
|
717
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
994
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
718
995
|
expect(result).to.equal(null);
|
|
719
996
|
});
|
|
720
997
|
it("should expand ReturnType with typeof function", () => {
|
|
@@ -724,9 +1001,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
724
1001
|
}
|
|
725
1002
|
type Result = ReturnType<typeof add>;
|
|
726
1003
|
`;
|
|
727
|
-
const {
|
|
1004
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
728
1005
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
729
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType",
|
|
1006
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", binding, stubConvertType);
|
|
730
1007
|
expect(result).not.to.equal(null);
|
|
731
1008
|
expect(result?.kind).to.equal("primitiveType");
|
|
732
1009
|
if (result?.kind === "primitiveType") {
|
|
@@ -739,9 +1016,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
739
1016
|
const source = `
|
|
740
1017
|
type Result = Parameters<(x: string, y: number) => void>;
|
|
741
1018
|
`;
|
|
742
|
-
const {
|
|
1019
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
743
1020
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
744
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters",
|
|
1021
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", binding, stubConvertType);
|
|
745
1022
|
expect(result).not.to.equal(null);
|
|
746
1023
|
// Parameters returns a tuple type - the exact representation depends on TypeScript
|
|
747
1024
|
});
|
|
@@ -749,20 +1026,20 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
749
1026
|
const source = `
|
|
750
1027
|
type Result = Parameters<() => void>;
|
|
751
1028
|
`;
|
|
752
|
-
const {
|
|
1029
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
753
1030
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
754
1031
|
// Empty tuple may return null (falls through to referenceType)
|
|
755
1032
|
// or may return an expanded type - both are acceptable behaviors
|
|
756
1033
|
// The key is that it doesn't throw an error
|
|
757
|
-
expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters",
|
|
1034
|
+
expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", binding, stubConvertType);
|
|
758
1035
|
});
|
|
759
1036
|
it("should expand Parameters with single parameter", () => {
|
|
760
1037
|
const source = `
|
|
761
1038
|
type Result = Parameters<(x: boolean) => void>;
|
|
762
1039
|
`;
|
|
763
|
-
const {
|
|
1040
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
764
1041
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
765
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters",
|
|
1042
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", binding, stubConvertType);
|
|
766
1043
|
expect(result).not.to.equal(null);
|
|
767
1044
|
});
|
|
768
1045
|
it("should return null for Parameters<T> where T is a type parameter", () => {
|
|
@@ -774,7 +1051,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
774
1051
|
fn(...args);
|
|
775
1052
|
}
|
|
776
1053
|
`;
|
|
777
|
-
const {
|
|
1054
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
778
1055
|
let typeRef = null;
|
|
779
1056
|
const visitor = (node) => {
|
|
780
1057
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -785,7 +1062,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
785
1062
|
ts.forEachChild(node, visitor);
|
|
786
1063
|
};
|
|
787
1064
|
ts.forEachChild(sourceFile, visitor);
|
|
788
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters",
|
|
1065
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", binding, stubConvertType);
|
|
789
1066
|
expect(result).to.equal(null);
|
|
790
1067
|
});
|
|
791
1068
|
it("should expand Parameters with typeof function", () => {
|
|
@@ -793,9 +1070,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
793
1070
|
function greet(name: string, age: number): void {}
|
|
794
1071
|
type Result = Parameters<typeof greet>;
|
|
795
1072
|
`;
|
|
796
|
-
const {
|
|
1073
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
797
1074
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
798
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters",
|
|
1075
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", binding, stubConvertType);
|
|
799
1076
|
expect(result).not.to.equal(null);
|
|
800
1077
|
});
|
|
801
1078
|
});
|
|
@@ -804,9 +1081,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
804
1081
|
const source = `
|
|
805
1082
|
type Result = Awaited<Promise<string>>;
|
|
806
1083
|
`;
|
|
807
|
-
const {
|
|
1084
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
808
1085
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
809
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1086
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
810
1087
|
expect(result).not.to.equal(null);
|
|
811
1088
|
expect(result?.kind).to.equal("primitiveType");
|
|
812
1089
|
if (result?.kind === "primitiveType") {
|
|
@@ -817,9 +1094,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
817
1094
|
const source = `
|
|
818
1095
|
type Result = Awaited<Promise<Promise<number>>>;
|
|
819
1096
|
`;
|
|
820
|
-
const {
|
|
1097
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
821
1098
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
822
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1099
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
823
1100
|
expect(result).not.to.equal(null);
|
|
824
1101
|
expect(result?.kind).to.equal("primitiveType");
|
|
825
1102
|
if (result?.kind === "primitiveType") {
|
|
@@ -830,9 +1107,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
830
1107
|
const source = `
|
|
831
1108
|
type Result = Awaited<string>;
|
|
832
1109
|
`;
|
|
833
|
-
const {
|
|
1110
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
834
1111
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
835
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1112
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
836
1113
|
expect(result).not.to.equal(null);
|
|
837
1114
|
expect(result?.kind).to.equal("primitiveType");
|
|
838
1115
|
if (result?.kind === "primitiveType") {
|
|
@@ -843,9 +1120,9 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
843
1120
|
const source = `
|
|
844
1121
|
type Result = Awaited<Promise<string> | Promise<number>>;
|
|
845
1122
|
`;
|
|
846
|
-
const {
|
|
1123
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
847
1124
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
848
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1125
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
849
1126
|
expect(result).not.to.equal(null);
|
|
850
1127
|
// Should be string | number
|
|
851
1128
|
expect(result?.kind).to.equal("unionType");
|
|
@@ -856,7 +1133,7 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
856
1133
|
return await promise;
|
|
857
1134
|
}
|
|
858
1135
|
`;
|
|
859
|
-
const {
|
|
1136
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
860
1137
|
let typeRef = null;
|
|
861
1138
|
const visitor = (node) => {
|
|
862
1139
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -867,16 +1144,16 @@ describe("Conditional Utility Type Expansion", () => {
|
|
|
867
1144
|
ts.forEachChild(node, visitor);
|
|
868
1145
|
};
|
|
869
1146
|
ts.forEachChild(sourceFile, visitor);
|
|
870
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1147
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
871
1148
|
expect(result).to.equal(null);
|
|
872
1149
|
});
|
|
873
1150
|
it("should expand Awaited<null> to null", () => {
|
|
874
1151
|
const source = `
|
|
875
1152
|
type Result = Awaited<null>;
|
|
876
1153
|
`;
|
|
877
|
-
const {
|
|
1154
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
878
1155
|
const typeRef = findTypeAliasReference(sourceFile, "Result");
|
|
879
|
-
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited",
|
|
1156
|
+
const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", binding, stubConvertType);
|
|
880
1157
|
expect(result).not.to.equal(null);
|
|
881
1158
|
expect(result?.kind).to.equal("primitiveType");
|
|
882
1159
|
if (result?.kind === "primitiveType") {
|
|
@@ -891,9 +1168,9 @@ describe("Record Type Expansion", () => {
|
|
|
891
1168
|
const source = `
|
|
892
1169
|
type Config = Record<"a" | "b", number>;
|
|
893
1170
|
`;
|
|
894
|
-
const {
|
|
1171
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
895
1172
|
const typeRef = findTypeAliasReference(sourceFile, "Config");
|
|
896
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1173
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
897
1174
|
expect(result).not.to.equal(null);
|
|
898
1175
|
expect(result?.kind).to.equal("objectType");
|
|
899
1176
|
expect(result?.members).to.have.length(2);
|
|
@@ -907,9 +1184,9 @@ describe("Record Type Expansion", () => {
|
|
|
907
1184
|
const source = `
|
|
908
1185
|
type IndexedConfig = Record<1 | 2, string>;
|
|
909
1186
|
`;
|
|
910
|
-
const {
|
|
1187
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
911
1188
|
const typeRef = findTypeAliasReference(sourceFile, "IndexedConfig");
|
|
912
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1189
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
913
1190
|
expect(result).not.to.equal(null);
|
|
914
1191
|
expect(result?.kind).to.equal("objectType");
|
|
915
1192
|
expect(result?.members).to.have.length(2);
|
|
@@ -924,9 +1201,9 @@ describe("Record Type Expansion", () => {
|
|
|
924
1201
|
const source = `
|
|
925
1202
|
type MixedConfig = Record<"name" | "age" | "email", boolean>;
|
|
926
1203
|
`;
|
|
927
|
-
const {
|
|
1204
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
928
1205
|
const typeRef = findTypeAliasReference(sourceFile, "MixedConfig");
|
|
929
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1206
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
930
1207
|
expect(result).not.to.equal(null);
|
|
931
1208
|
expect(result?.kind).to.equal("objectType");
|
|
932
1209
|
expect(result?.members).to.have.length(3);
|
|
@@ -937,9 +1214,9 @@ describe("Record Type Expansion", () => {
|
|
|
937
1214
|
const source = `
|
|
938
1215
|
type Dictionary = Record<string, number>;
|
|
939
1216
|
`;
|
|
940
|
-
const {
|
|
1217
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
941
1218
|
const typeRef = findTypeAliasReference(sourceFile, "Dictionary");
|
|
942
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1219
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
943
1220
|
// Should return null - use IrDictionaryType instead
|
|
944
1221
|
expect(result).to.equal(null);
|
|
945
1222
|
});
|
|
@@ -947,9 +1224,9 @@ describe("Record Type Expansion", () => {
|
|
|
947
1224
|
const source = `
|
|
948
1225
|
type NumberDictionary = Record<number, string>;
|
|
949
1226
|
`;
|
|
950
|
-
const {
|
|
1227
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
951
1228
|
const typeRef = findTypeAliasReference(sourceFile, "NumberDictionary");
|
|
952
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1229
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
953
1230
|
// Should return null - use IrDictionaryType instead
|
|
954
1231
|
expect(result).to.equal(null);
|
|
955
1232
|
});
|
|
@@ -959,7 +1236,7 @@ describe("Record Type Expansion", () => {
|
|
|
959
1236
|
return {} as Record<K, number>;
|
|
960
1237
|
}
|
|
961
1238
|
`;
|
|
962
|
-
const {
|
|
1239
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
963
1240
|
let typeRef = null;
|
|
964
1241
|
const visitor = (node) => {
|
|
965
1242
|
if (ts.isTypeReferenceNode(node) &&
|
|
@@ -971,7 +1248,7 @@ describe("Record Type Expansion", () => {
|
|
|
971
1248
|
ts.forEachChild(node, visitor);
|
|
972
1249
|
};
|
|
973
1250
|
ts.forEachChild(sourceFile, visitor);
|
|
974
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1251
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
975
1252
|
// Should return null - type parameter can't be expanded
|
|
976
1253
|
expect(result).to.equal(null);
|
|
977
1254
|
});
|
|
@@ -981,9 +1258,9 @@ describe("Record Type Expansion", () => {
|
|
|
981
1258
|
const source = `
|
|
982
1259
|
type AnyKeyRecord = Record<PropertyKey, number>;
|
|
983
1260
|
`;
|
|
984
|
-
const {
|
|
1261
|
+
const { binding, sourceFile } = createTestProgram(source);
|
|
985
1262
|
const typeRef = findTypeAliasReference(sourceFile, "AnyKeyRecord");
|
|
986
|
-
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"),
|
|
1263
|
+
const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), binding, stubConvertType);
|
|
987
1264
|
// Should return null - PropertyKey is not a finite set of literals
|
|
988
1265
|
// and should fall through to referenceType (not dictionaryType)
|
|
989
1266
|
expect(result).to.equal(null);
|
|
@@ -1018,6 +1295,7 @@ describe("Record Type Expansion", () => {
|
|
|
1018
1295
|
const keyTypeNode = foundTypeRef.typeArguments?.[0];
|
|
1019
1296
|
expect(keyTypeNode).not.to.equal(undefined);
|
|
1020
1297
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1298
|
+
// NOTE: This test uses getTypeAtLocation to verify TS internal behavior
|
|
1021
1299
|
const keyTsType = checker.getTypeAtLocation(keyTypeNode);
|
|
1022
1300
|
// The key type should be a type parameter, not string
|
|
1023
1301
|
expect(!!(keyTsType.flags & ts.TypeFlags.TypeParameter)).to.equal(true);
|