@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.
Files changed (507) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/graph/builder.js +2 -2
  3. package/dist/graph/builder.js.map +1 -1
  4. package/dist/graph/extraction/imports.js +1 -1
  5. package/dist/graph/extraction/imports.js.map +1 -1
  6. package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
  7. package/dist/graph/extraction/orchestrator.js +3 -2
  8. package/dist/graph/extraction/orchestrator.js.map +1 -1
  9. package/dist/ir/binding/index.d.ts +155 -0
  10. package/dist/ir/binding/index.d.ts.map +1 -0
  11. package/dist/ir/binding/index.js +1035 -0
  12. package/dist/ir/binding/index.js.map +1 -0
  13. package/dist/ir/binding-resolution.test.js +193 -52
  14. package/dist/ir/binding-resolution.test.js.map +1 -1
  15. package/dist/ir/bindings-disambiguation.test.d.ts +11 -0
  16. package/dist/ir/bindings-disambiguation.test.d.ts.map +1 -0
  17. package/dist/ir/bindings-disambiguation.test.js +416 -0
  18. package/dist/ir/bindings-disambiguation.test.js.map +1 -0
  19. package/dist/ir/builder/exports.d.ts +20 -2
  20. package/dist/ir/builder/exports.d.ts.map +1 -1
  21. package/dist/ir/builder/exports.js +65 -6
  22. package/dist/ir/builder/exports.js.map +1 -1
  23. package/dist/ir/builder/imports.d.ts +9 -5
  24. package/dist/ir/builder/imports.d.ts.map +1 -1
  25. package/dist/ir/builder/imports.js +20 -31
  26. package/dist/ir/builder/imports.js.map +1 -1
  27. package/dist/ir/builder/orchestrator.d.ts +10 -1
  28. package/dist/ir/builder/orchestrator.d.ts.map +1 -1
  29. package/dist/ir/builder/orchestrator.js +32 -15
  30. package/dist/ir/builder/orchestrator.js.map +1 -1
  31. package/dist/ir/builder/statements.d.ts +7 -1
  32. package/dist/ir/builder/statements.d.ts.map +1 -1
  33. package/dist/ir/builder/statements.js +7 -2
  34. package/dist/ir/builder/statements.js.map +1 -1
  35. package/dist/ir/builder/types.d.ts +2 -0
  36. package/dist/ir/builder/types.d.ts.map +1 -1
  37. package/dist/ir/builder/validation.d.ts +4 -1
  38. package/dist/ir/builder/validation.d.ts.map +1 -1
  39. package/dist/ir/builder/validation.js +37 -37
  40. package/dist/ir/builder/validation.js.map +1 -1
  41. package/dist/ir/builder.test.js +55 -112
  42. package/dist/ir/builder.test.js.map +1 -1
  43. package/dist/ir/converters/anonymous-synthesis.d.ts +30 -8
  44. package/dist/ir/converters/anonymous-synthesis.d.ts.map +1 -1
  45. package/dist/ir/converters/anonymous-synthesis.js +46 -55
  46. package/dist/ir/converters/anonymous-synthesis.js.map +1 -1
  47. package/dist/ir/converters/context.d.ts +40 -0
  48. package/dist/ir/converters/context.d.ts.map +1 -0
  49. package/dist/ir/converters/context.js +25 -0
  50. package/dist/ir/converters/context.js.map +1 -0
  51. package/dist/ir/converters/expressions/access.d.ts +6 -1
  52. package/dist/ir/converters/expressions/access.d.ts.map +1 -1
  53. package/dist/ir/converters/expressions/access.js +389 -43
  54. package/dist/ir/converters/expressions/access.js.map +1 -1
  55. package/dist/ir/converters/expressions/calls.d.ts +24 -3
  56. package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
  57. package/dist/ir/converters/expressions/calls.js +674 -397
  58. package/dist/ir/converters/expressions/calls.js.map +1 -1
  59. package/dist/ir/converters/expressions/collections.d.ts +16 -3
  60. package/dist/ir/converters/expressions/collections.d.ts.map +1 -1
  61. package/dist/ir/converters/expressions/collections.js +300 -46
  62. package/dist/ir/converters/expressions/collections.js.map +1 -1
  63. package/dist/ir/converters/expressions/functions.d.ts +10 -3
  64. package/dist/ir/converters/expressions/functions.d.ts.map +1 -1
  65. package/dist/ir/converters/expressions/functions.js +158 -32
  66. package/dist/ir/converters/expressions/functions.js.map +1 -1
  67. package/dist/ir/converters/expressions/helpers.d.ts +22 -23
  68. package/dist/ir/converters/expressions/helpers.d.ts.map +1 -1
  69. package/dist/ir/converters/expressions/helpers.js +242 -239
  70. package/dist/ir/converters/expressions/helpers.js.map +1 -1
  71. package/dist/ir/converters/expressions/index.d.ts +1 -1
  72. package/dist/ir/converters/expressions/index.d.ts.map +1 -1
  73. package/dist/ir/converters/expressions/index.js +1 -1
  74. package/dist/ir/converters/expressions/index.js.map +1 -1
  75. package/dist/ir/converters/expressions/literals.d.ts +12 -12
  76. package/dist/ir/converters/expressions/literals.d.ts.map +1 -1
  77. package/dist/ir/converters/expressions/literals.js +62 -17
  78. package/dist/ir/converters/expressions/literals.js.map +1 -1
  79. package/dist/ir/converters/expressions/numeric-recovery.test.d.ts +5 -2
  80. package/dist/ir/converters/expressions/numeric-recovery.test.d.ts.map +1 -1
  81. package/dist/ir/converters/expressions/numeric-recovery.test.js +62 -49
  82. package/dist/ir/converters/expressions/numeric-recovery.test.js.map +1 -1
  83. package/dist/ir/converters/expressions/operators.d.ts +13 -4
  84. package/dist/ir/converters/expressions/operators.d.ts.map +1 -1
  85. package/dist/ir/converters/expressions/operators.js +183 -33
  86. package/dist/ir/converters/expressions/operators.js.map +1 -1
  87. package/dist/ir/converters/expressions/other.d.ts +11 -3
  88. package/dist/ir/converters/expressions/other.d.ts.map +1 -1
  89. package/dist/ir/converters/expressions/other.js +26 -10
  90. package/dist/ir/converters/expressions/other.js.map +1 -1
  91. package/dist/ir/converters/flow-narrowing.d.ts +27 -0
  92. package/dist/ir/converters/flow-narrowing.d.ts.map +1 -0
  93. package/dist/ir/converters/flow-narrowing.js +73 -0
  94. package/dist/ir/converters/flow-narrowing.js.map +1 -0
  95. package/dist/ir/converters/statements/control/blocks.d.ts +8 -2
  96. package/dist/ir/converters/statements/control/blocks.d.ts.map +1 -1
  97. package/dist/ir/converters/statements/control/blocks.js +7 -2
  98. package/dist/ir/converters/statements/control/blocks.js.map +1 -1
  99. package/dist/ir/converters/statements/control/conditionals.d.ts +14 -4
  100. package/dist/ir/converters/statements/control/conditionals.d.ts.map +1 -1
  101. package/dist/ir/converters/statements/control/conditionals.js +36 -10
  102. package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
  103. package/dist/ir/converters/statements/control/exceptions.d.ts +10 -3
  104. package/dist/ir/converters/statements/control/exceptions.d.ts.map +1 -1
  105. package/dist/ir/converters/statements/control/exceptions.js +13 -7
  106. package/dist/ir/converters/statements/control/exceptions.js.map +1 -1
  107. package/dist/ir/converters/statements/control/loops.d.ts +16 -5
  108. package/dist/ir/converters/statements/control/loops.d.ts.map +1 -1
  109. package/dist/ir/converters/statements/control/loops.js +25 -15
  110. package/dist/ir/converters/statements/control/loops.js.map +1 -1
  111. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts +3 -2
  112. package/dist/ir/converters/statements/declarations/classes/constructors.d.ts.map +1 -1
  113. package/dist/ir/converters/statements/declarations/classes/constructors.js +11 -7
  114. package/dist/ir/converters/statements/declarations/classes/constructors.js.map +1 -1
  115. package/dist/ir/converters/statements/declarations/classes/methods.d.ts +2 -1
  116. package/dist/ir/converters/statements/declarations/classes/methods.d.ts.map +1 -1
  117. package/dist/ir/converters/statements/declarations/classes/methods.js +63 -11
  118. package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
  119. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts +2 -1
  120. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
  121. package/dist/ir/converters/statements/declarations/classes/orchestrator.js +60 -40
  122. package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
  123. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts +6 -2
  124. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts.map +1 -1
  125. package/dist/ir/converters/statements/declarations/classes/override-detection.js +49 -50
  126. package/dist/ir/converters/statements/declarations/classes/override-detection.js.map +1 -1
  127. package/dist/ir/converters/statements/declarations/classes/properties.d.ts +9 -1
  128. package/dist/ir/converters/statements/declarations/classes/properties.d.ts.map +1 -1
  129. package/dist/ir/converters/statements/declarations/classes/properties.js +119 -16
  130. package/dist/ir/converters/statements/declarations/classes/properties.js.map +1 -1
  131. package/dist/ir/converters/statements/declarations/enums.d.ts +2 -1
  132. package/dist/ir/converters/statements/declarations/enums.d.ts.map +1 -1
  133. package/dist/ir/converters/statements/declarations/enums.js +8 -2
  134. package/dist/ir/converters/statements/declarations/enums.js.map +1 -1
  135. package/dist/ir/converters/statements/declarations/functions.d.ts +2 -1
  136. package/dist/ir/converters/statements/declarations/functions.d.ts.map +1 -1
  137. package/dist/ir/converters/statements/declarations/functions.js +11 -6
  138. package/dist/ir/converters/statements/declarations/functions.js.map +1 -1
  139. package/dist/ir/converters/statements/declarations/index.d.ts +3 -1
  140. package/dist/ir/converters/statements/declarations/index.d.ts.map +1 -1
  141. package/dist/ir/converters/statements/declarations/index.js +3 -1
  142. package/dist/ir/converters/statements/declarations/index.js.map +1 -1
  143. package/dist/ir/converters/statements/declarations/interfaces.d.ts +3 -2
  144. package/dist/ir/converters/statements/declarations/interfaces.d.ts.map +1 -1
  145. package/dist/ir/converters/statements/declarations/interfaces.js +26 -20
  146. package/dist/ir/converters/statements/declarations/interfaces.js.map +1 -1
  147. package/dist/ir/converters/statements/declarations/registry.d.ts +72 -0
  148. package/dist/ir/converters/statements/declarations/registry.d.ts.map +1 -1
  149. package/dist/ir/converters/statements/declarations/registry.js +92 -0
  150. package/dist/ir/converters/statements/declarations/registry.js.map +1 -1
  151. package/dist/ir/converters/statements/declarations/type-aliases.d.ts +2 -1
  152. package/dist/ir/converters/statements/declarations/type-aliases.d.ts.map +1 -1
  153. package/dist/ir/converters/statements/declarations/type-aliases.js +6 -4
  154. package/dist/ir/converters/statements/declarations/type-aliases.js.map +1 -1
  155. package/dist/ir/converters/statements/declarations/variables.d.ts +11 -1
  156. package/dist/ir/converters/statements/declarations/variables.d.ts.map +1 -1
  157. package/dist/ir/converters/statements/declarations/variables.js +123 -19
  158. package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
  159. package/dist/ir/converters/statements/declarations.d.ts +4 -1
  160. package/dist/ir/converters/statements/declarations.d.ts.map +1 -1
  161. package/dist/ir/converters/statements/declarations.js +4 -1
  162. package/dist/ir/converters/statements/declarations.js.map +1 -1
  163. package/dist/ir/converters/statements/helpers.d.ts +4 -3
  164. package/dist/ir/converters/statements/helpers.d.ts.map +1 -1
  165. package/dist/ir/converters/statements/helpers.js +55 -31
  166. package/dist/ir/converters/statements/helpers.js.map +1 -1
  167. package/dist/ir/converters/statements/index.d.ts +1 -1
  168. package/dist/ir/converters/statements/index.d.ts.map +1 -1
  169. package/dist/ir/converters/statements/index.js +2 -1
  170. package/dist/ir/converters/statements/index.js.map +1 -1
  171. package/dist/ir/expression-converter.d.ts +10 -3
  172. package/dist/ir/expression-converter.d.ts.map +1 -1
  173. package/dist/ir/expression-converter.js +139 -57
  174. package/dist/ir/expression-converter.js.map +1 -1
  175. package/dist/ir/hierarchical-bindings-e2e.test.js +10 -6
  176. package/dist/ir/hierarchical-bindings-e2e.test.js.map +1 -1
  177. package/dist/ir/index.d.ts +5 -0
  178. package/dist/ir/index.d.ts.map +1 -1
  179. package/dist/ir/index.js +5 -0
  180. package/dist/ir/index.js.map +1 -1
  181. package/dist/ir/no-ts-type-inference.test.d.ts +17 -0
  182. package/dist/ir/no-ts-type-inference.test.d.ts.map +1 -0
  183. package/dist/ir/no-ts-type-inference.test.js +171 -0
  184. package/dist/ir/no-ts-type-inference.test.js.map +1 -0
  185. package/dist/ir/program-context.d.ts +87 -0
  186. package/dist/ir/program-context.d.ts.map +1 -0
  187. package/dist/ir/program-context.js +289 -0
  188. package/dist/ir/program-context.js.map +1 -0
  189. package/dist/ir/statement-converter.d.ts +14 -4
  190. package/dist/ir/statement-converter.d.ts.map +1 -1
  191. package/dist/ir/statement-converter.js +31 -21
  192. package/dist/ir/statement-converter.js.map +1 -1
  193. package/dist/ir/syntax/binding-patterns.d.ts +22 -0
  194. package/dist/ir/syntax/binding-patterns.d.ts.map +1 -0
  195. package/dist/ir/{type-converter/patterns.js → syntax/binding-patterns.js} +34 -8
  196. package/dist/ir/syntax/binding-patterns.js.map +1 -0
  197. package/dist/ir/thisarg-inference.test.d.ts +8 -0
  198. package/dist/ir/thisarg-inference.test.d.ts.map +1 -0
  199. package/dist/ir/thisarg-inference.test.js +94 -0
  200. package/dist/ir/thisarg-inference.test.js.map +1 -0
  201. package/dist/ir/type-system/index.d.ts +21 -0
  202. package/dist/ir/type-system/index.d.ts.map +1 -0
  203. package/dist/ir/type-system/index.js +43 -0
  204. package/dist/ir/type-system/index.js.map +1 -0
  205. package/dist/ir/type-system/internal/handle-types.d.ts +105 -0
  206. package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -0
  207. package/dist/ir/type-system/internal/handle-types.js +13 -0
  208. package/dist/ir/type-system/internal/handle-types.js.map +1 -0
  209. package/dist/ir/type-system/internal/nominal-env.d.ts +66 -0
  210. package/dist/ir/type-system/internal/nominal-env.d.ts.map +1 -0
  211. package/dist/ir/type-system/internal/nominal-env.js +301 -0
  212. package/dist/ir/type-system/internal/nominal-env.js.map +1 -0
  213. package/dist/ir/type-system/internal/type-converter/arrays.d.ts +11 -0
  214. package/dist/ir/type-system/internal/type-converter/arrays.d.ts.map +1 -0
  215. package/dist/ir/{type-converter → type-system/internal/type-converter}/arrays.js +2 -2
  216. package/dist/ir/type-system/internal/type-converter/arrays.js.map +1 -0
  217. package/dist/ir/type-system/internal/type-converter/converter.d.ts +17 -0
  218. package/dist/ir/type-system/internal/type-converter/converter.d.ts.map +1 -0
  219. package/dist/ir/type-system/internal/type-converter/converter.js +16 -0
  220. package/dist/ir/type-system/internal/type-converter/converter.js.map +1 -0
  221. package/dist/ir/type-system/internal/type-converter/functions.d.ts +14 -0
  222. package/dist/ir/type-system/internal/type-converter/functions.d.ts.map +1 -0
  223. package/dist/ir/type-system/internal/type-converter/functions.js +66 -0
  224. package/dist/ir/type-system/internal/type-converter/functions.js.map +1 -0
  225. package/dist/ir/type-system/internal/type-converter/index.d.ts +11 -0
  226. package/dist/ir/type-system/internal/type-converter/index.d.ts.map +1 -0
  227. package/dist/ir/type-system/internal/type-converter/index.js +11 -0
  228. package/dist/ir/type-system/internal/type-converter/index.js.map +1 -0
  229. package/dist/ir/type-system/internal/type-converter/inference.d.ts +37 -0
  230. package/dist/ir/type-system/internal/type-converter/inference.d.ts.map +1 -0
  231. package/dist/ir/type-system/internal/type-converter/inference.js +32 -0
  232. package/dist/ir/type-system/internal/type-converter/inference.js.map +1 -0
  233. package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.d.ts +1 -1
  234. package/dist/ir/type-system/internal/type-converter/literals.d.ts.map +1 -0
  235. package/dist/ir/type-system/internal/type-converter/literals.js.map +1 -0
  236. package/dist/ir/type-system/internal/type-converter/objects.d.ts +20 -0
  237. package/dist/ir/type-system/internal/type-converter/objects.d.ts.map +1 -0
  238. package/dist/ir/{type-converter → type-system/internal/type-converter}/objects.js +56 -6
  239. package/dist/ir/type-system/internal/type-converter/objects.js.map +1 -0
  240. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.d.ts +3 -2
  241. package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -0
  242. package/dist/ir/{type-converter → type-system/internal/type-converter}/orchestrator.js +63 -21
  243. package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -0
  244. package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.d.ts +4 -4
  245. package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -0
  246. package/dist/ir/{type-converter → type-system/internal/type-converter}/primitives.js +2 -2
  247. package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -0
  248. package/dist/ir/{type-converter → type-system/internal/type-converter}/references.d.ts +3 -2
  249. package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -0
  250. package/dist/ir/type-system/internal/type-converter/references.js +545 -0
  251. package/dist/ir/type-system/internal/type-converter/references.js.map +1 -0
  252. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts +15 -0
  253. package/dist/ir/type-system/internal/type-converter/unions-intersections.d.ts.map +1 -0
  254. package/dist/ir/type-system/internal/type-converter/unions-intersections.js +22 -0
  255. package/dist/ir/type-system/internal/type-converter/unions-intersections.js.map +1 -0
  256. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.d.ts +23 -36
  257. package/dist/ir/type-system/internal/type-converter/utility-types.d.ts.map +1 -0
  258. package/dist/ir/type-system/internal/type-converter/utility-types.js +879 -0
  259. package/dist/ir/type-system/internal/type-converter/utility-types.js.map +1 -0
  260. package/dist/ir/type-system/internal/type-converter/utility-types.test.d.ts.map +1 -0
  261. package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.js +398 -120
  262. package/dist/ir/type-system/internal/type-converter/utility-types.test.js.map +1 -0
  263. package/dist/ir/type-system/internal/type-converter.d.ts +9 -0
  264. package/dist/ir/type-system/internal/type-converter.d.ts.map +1 -0
  265. package/dist/ir/type-system/internal/type-converter.js +9 -0
  266. package/dist/ir/type-system/internal/type-converter.js.map +1 -0
  267. package/dist/ir/type-system/internal/type-registry.d.ts +112 -0
  268. package/dist/ir/type-system/internal/type-registry.d.ts.map +1 -0
  269. package/dist/ir/type-system/internal/type-registry.js +535 -0
  270. package/dist/ir/type-system/internal/type-registry.js.map +1 -0
  271. package/dist/ir/type-system/internal/universe/alias-table.d.ts +92 -0
  272. package/dist/ir/type-system/internal/universe/alias-table.d.ts.map +1 -0
  273. package/dist/ir/type-system/internal/universe/alias-table.js +222 -0
  274. package/dist/ir/type-system/internal/universe/alias-table.js.map +1 -0
  275. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts +44 -0
  276. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -0
  277. package/dist/ir/type-system/internal/universe/clr-catalog.js +1192 -0
  278. package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -0
  279. package/dist/ir/type-system/internal/universe/index.d.ts +26 -0
  280. package/dist/ir/type-system/internal/universe/index.d.ts.map +1 -0
  281. package/dist/ir/type-system/internal/universe/index.js +30 -0
  282. package/dist/ir/type-system/internal/universe/index.js.map +1 -0
  283. package/dist/ir/type-system/internal/universe/resolution.d.ts +115 -0
  284. package/dist/ir/type-system/internal/universe/resolution.d.ts.map +1 -0
  285. package/dist/ir/type-system/internal/universe/resolution.js +181 -0
  286. package/dist/ir/type-system/internal/universe/resolution.js.map +1 -0
  287. package/dist/ir/type-system/internal/universe/source-catalog.d.ts +64 -0
  288. package/dist/ir/type-system/internal/universe/source-catalog.d.ts.map +1 -0
  289. package/dist/ir/type-system/internal/universe/source-catalog.js +96 -0
  290. package/dist/ir/type-system/internal/universe/source-catalog.js.map +1 -0
  291. package/dist/ir/type-system/internal/universe/types.d.ts +436 -0
  292. package/dist/ir/type-system/internal/universe/types.d.ts.map +1 -0
  293. package/dist/ir/type-system/internal/universe/types.js +69 -0
  294. package/dist/ir/type-system/internal/universe/types.js.map +1 -0
  295. package/dist/ir/type-system/internal/universe/unified-universe.d.ts +70 -0
  296. package/dist/ir/type-system/internal/universe/unified-universe.d.ts.map +1 -0
  297. package/dist/ir/type-system/internal/universe/unified-universe.js +319 -0
  298. package/dist/ir/type-system/internal/universe/unified-universe.js.map +1 -0
  299. package/dist/ir/type-system/type-system.d.ts +617 -0
  300. package/dist/ir/type-system/type-system.d.ts.map +1 -0
  301. package/dist/ir/type-system/type-system.js +2579 -0
  302. package/dist/ir/type-system/type-system.js.map +1 -0
  303. package/dist/ir/type-system/types.d.ts +176 -0
  304. package/dist/ir/type-system/types.d.ts.map +1 -0
  305. package/dist/ir/type-system/types.js +80 -0
  306. package/dist/ir/type-system/types.js.map +1 -0
  307. package/dist/ir/types/expressions.d.ts +35 -7
  308. package/dist/ir/types/expressions.d.ts.map +1 -1
  309. package/dist/ir/types/helpers.d.ts +22 -2
  310. package/dist/ir/types/helpers.d.ts.map +1 -1
  311. package/dist/ir/types/index.d.ts +4 -2
  312. package/dist/ir/types/index.d.ts.map +1 -1
  313. package/dist/ir/types/index.js +1 -0
  314. package/dist/ir/types/index.js.map +1 -1
  315. package/dist/ir/types/ir-substitution.d.ts +144 -0
  316. package/dist/ir/types/ir-substitution.d.ts.map +1 -0
  317. package/dist/ir/types/ir-substitution.js +569 -0
  318. package/dist/ir/types/ir-substitution.js.map +1 -0
  319. package/dist/ir/types/ir-types.d.ts +10 -4
  320. package/dist/ir/types/ir-types.d.ts.map +1 -1
  321. package/dist/ir/types/numeric-helpers.d.ts +2 -1
  322. package/dist/ir/types/numeric-helpers.d.ts.map +1 -1
  323. package/dist/ir/types/numeric-helpers.js +9 -3
  324. package/dist/ir/types/numeric-helpers.js.map +1 -1
  325. package/dist/ir/types/statements.d.ts +22 -1
  326. package/dist/ir/types/statements.d.ts.map +1 -1
  327. package/dist/ir/types.d.ts +1 -1
  328. package/dist/ir/types.d.ts.map +1 -1
  329. package/dist/ir/types.js.map +1 -1
  330. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  331. package/dist/ir/validation/anonymous-type-lowering-pass.js +153 -8
  332. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  333. package/dist/ir/validation/arrow-return-finalization-pass.d.ts +28 -0
  334. package/dist/ir/validation/arrow-return-finalization-pass.d.ts.map +1 -0
  335. package/dist/ir/validation/arrow-return-finalization-pass.js +416 -0
  336. package/dist/ir/validation/arrow-return-finalization-pass.js.map +1 -0
  337. package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
  338. package/dist/ir/validation/attribute-collection-pass.js +40 -6
  339. package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
  340. package/dist/ir/validation/attribute-collection-pass.test.js +43 -36
  341. package/dist/ir/validation/attribute-collection-pass.test.js.map +1 -1
  342. package/dist/ir/validation/char-validation-pass.d.ts +26 -0
  343. package/dist/ir/validation/char-validation-pass.d.ts.map +1 -0
  344. package/dist/ir/validation/char-validation-pass.js +495 -0
  345. package/dist/ir/validation/char-validation-pass.js.map +1 -0
  346. package/dist/ir/validation/index.d.ts +3 -0
  347. package/dist/ir/validation/index.d.ts.map +1 -1
  348. package/dist/ir/validation/index.js +3 -0
  349. package/dist/ir/validation/index.js.map +1 -1
  350. package/dist/ir/validation/numeric-coercion-pass.d.ts +22 -16
  351. package/dist/ir/validation/numeric-coercion-pass.d.ts.map +1 -1
  352. package/dist/ir/validation/numeric-coercion-pass.js +159 -51
  353. package/dist/ir/validation/numeric-coercion-pass.js.map +1 -1
  354. package/dist/ir/validation/numeric-invariants.test.js +72 -108
  355. package/dist/ir/validation/numeric-invariants.test.js.map +1 -1
  356. package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
  357. package/dist/ir/validation/numeric-proof-pass.js +71 -23
  358. package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
  359. package/dist/ir/validation/rest-type-synthesis-pass.d.ts +24 -0
  360. package/dist/ir/validation/rest-type-synthesis-pass.d.ts.map +1 -0
  361. package/dist/ir/validation/rest-type-synthesis-pass.js +417 -0
  362. package/dist/ir/validation/rest-type-synthesis-pass.js.map +1 -0
  363. package/dist/ir/validation/soundness-gate.d.ts +11 -1
  364. package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
  365. package/dist/ir/validation/soundness-gate.js +42 -10
  366. package/dist/ir/validation/soundness-gate.js.map +1 -1
  367. package/dist/ir/validation/soundness-gate.test.js +19 -2
  368. package/dist/ir/validation/soundness-gate.test.js.map +1 -1
  369. package/dist/ir/validation/virtual-marking-pass.d.ts +16 -0
  370. package/dist/ir/validation/virtual-marking-pass.d.ts.map +1 -0
  371. package/dist/ir/validation/virtual-marking-pass.js +77 -0
  372. package/dist/ir/validation/virtual-marking-pass.js.map +1 -0
  373. package/dist/ir/validation/yield-lowering-pass.test.js +2 -2
  374. package/dist/ir/validation/yield-lowering-pass.test.js.map +1 -1
  375. package/dist/program/bindings.d.ts +44 -0
  376. package/dist/program/bindings.d.ts.map +1 -1
  377. package/dist/program/bindings.js +248 -2
  378. package/dist/program/bindings.js.map +1 -1
  379. package/dist/program/bindings.test.js +30 -0
  380. package/dist/program/bindings.test.js.map +1 -1
  381. package/dist/program/creation.d.ts.map +1 -1
  382. package/dist/program/creation.js +158 -4
  383. package/dist/program/creation.js.map +1 -1
  384. package/dist/program/dependency-graph.d.ts.map +1 -1
  385. package/dist/program/dependency-graph.js +33 -26
  386. package/dist/program/dependency-graph.js.map +1 -1
  387. package/dist/program/index.d.ts +1 -1
  388. package/dist/program/index.d.ts.map +1 -1
  389. package/dist/program/types.d.ts +7 -8
  390. package/dist/program/types.d.ts.map +1 -1
  391. package/dist/resolver/clr-bindings-resolver.d.ts +6 -0
  392. package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
  393. package/dist/resolver/clr-bindings-resolver.js +185 -39
  394. package/dist/resolver/clr-bindings-resolver.js.map +1 -1
  395. package/dist/resolver/clr-bindings-resolver.test.d.ts +2 -0
  396. package/dist/resolver/clr-bindings-resolver.test.d.ts.map +1 -0
  397. package/dist/resolver/clr-bindings-resolver.test.js +161 -0
  398. package/dist/resolver/clr-bindings-resolver.test.js.map +1 -0
  399. package/dist/resolver/import-resolution.d.ts +16 -1
  400. package/dist/resolver/import-resolution.d.ts.map +1 -1
  401. package/dist/resolver/import-resolution.js +29 -12
  402. package/dist/resolver/import-resolution.js.map +1 -1
  403. package/dist/resolver/namespace.d.ts +2 -1
  404. package/dist/resolver/namespace.d.ts.map +1 -1
  405. package/dist/resolver/namespace.js +5 -2
  406. package/dist/resolver/namespace.js.map +1 -1
  407. package/dist/resolver/namespace.test.js +6 -6
  408. package/dist/resolver/naming-policy.d.ts +20 -0
  409. package/dist/resolver/naming-policy.d.ts.map +1 -0
  410. package/dist/resolver/naming-policy.js +40 -0
  411. package/dist/resolver/naming-policy.js.map +1 -0
  412. package/dist/resolver/naming.d.ts +2 -5
  413. package/dist/resolver/naming.d.ts.map +1 -1
  414. package/dist/resolver/naming.js +3 -20
  415. package/dist/resolver/naming.js.map +1 -1
  416. package/dist/resolver.d.ts +2 -0
  417. package/dist/resolver.d.ts.map +1 -1
  418. package/dist/resolver.js +1 -0
  419. package/dist/resolver.js.map +1 -1
  420. package/dist/resolver.test.js +8 -3
  421. package/dist/resolver.test.js.map +1 -1
  422. package/dist/symbol-table/builder.d.ts +3 -1
  423. package/dist/symbol-table/builder.d.ts.map +1 -1
  424. package/dist/symbol-table/builder.js +9 -8
  425. package/dist/symbol-table/builder.js.map +1 -1
  426. package/dist/symbol-table/types.d.ts +2 -2
  427. package/dist/symbol-table/types.d.ts.map +1 -1
  428. package/dist/types/diagnostic.d.ts +12 -2
  429. package/dist/types/diagnostic.d.ts.map +1 -1
  430. package/dist/types/diagnostic.js +5 -1
  431. package/dist/types/diagnostic.js.map +1 -1
  432. package/dist/validation/core-intrinsics.d.ts +18 -0
  433. package/dist/validation/core-intrinsics.d.ts.map +1 -0
  434. package/dist/validation/core-intrinsics.js +186 -0
  435. package/dist/validation/core-intrinsics.js.map +1 -0
  436. package/dist/validation/extension-methods.d.ts +17 -0
  437. package/dist/validation/extension-methods.d.ts.map +1 -0
  438. package/dist/validation/extension-methods.js +133 -0
  439. package/dist/validation/extension-methods.js.map +1 -0
  440. package/dist/validation/generics.d.ts.map +1 -1
  441. package/dist/validation/generics.js +1 -129
  442. package/dist/validation/generics.js.map +1 -1
  443. package/dist/validation/imports.js +1 -1
  444. package/dist/validation/imports.js.map +1 -1
  445. package/dist/validation/index.d.ts +2 -0
  446. package/dist/validation/index.d.ts.map +1 -1
  447. package/dist/validation/index.js +2 -0
  448. package/dist/validation/index.js.map +1 -1
  449. package/dist/validation/orchestrator.d.ts.map +1 -1
  450. package/dist/validation/orchestrator.js +4 -0
  451. package/dist/validation/orchestrator.js.map +1 -1
  452. package/dist/validation/static-safety.d.ts +1 -0
  453. package/dist/validation/static-safety.d.ts.map +1 -1
  454. package/dist/validation/static-safety.js +366 -96
  455. package/dist/validation/static-safety.js.map +1 -1
  456. package/dist/validator.test.js +123 -1
  457. package/dist/validator.test.js.map +1 -1
  458. package/package.json +2 -2
  459. package/dist/ir/type-converter/arrays.d.ts +0 -10
  460. package/dist/ir/type-converter/arrays.d.ts.map +0 -1
  461. package/dist/ir/type-converter/arrays.js.map +0 -1
  462. package/dist/ir/type-converter/converter.d.ts +0 -6
  463. package/dist/ir/type-converter/converter.d.ts.map +0 -1
  464. package/dist/ir/type-converter/converter.js +0 -6
  465. package/dist/ir/type-converter/converter.js.map +0 -1
  466. package/dist/ir/type-converter/functions.d.ts +0 -10
  467. package/dist/ir/type-converter/functions.d.ts.map +0 -1
  468. package/dist/ir/type-converter/functions.js +0 -15
  469. package/dist/ir/type-converter/functions.js.map +0 -1
  470. package/dist/ir/type-converter/index.d.ts +0 -7
  471. package/dist/ir/type-converter/index.d.ts.map +0 -1
  472. package/dist/ir/type-converter/index.js +0 -7
  473. package/dist/ir/type-converter/index.js.map +0 -1
  474. package/dist/ir/type-converter/inference.d.ts +0 -32
  475. package/dist/ir/type-converter/inference.d.ts.map +0 -1
  476. package/dist/ir/type-converter/inference.js +0 -297
  477. package/dist/ir/type-converter/inference.js.map +0 -1
  478. package/dist/ir/type-converter/literals.d.ts.map +0 -1
  479. package/dist/ir/type-converter/literals.js.map +0 -1
  480. package/dist/ir/type-converter/objects.d.ts +0 -16
  481. package/dist/ir/type-converter/objects.d.ts.map +0 -1
  482. package/dist/ir/type-converter/objects.js.map +0 -1
  483. package/dist/ir/type-converter/orchestrator.d.ts.map +0 -1
  484. package/dist/ir/type-converter/orchestrator.js.map +0 -1
  485. package/dist/ir/type-converter/patterns.d.ts +0 -10
  486. package/dist/ir/type-converter/patterns.d.ts.map +0 -1
  487. package/dist/ir/type-converter/patterns.js.map +0 -1
  488. package/dist/ir/type-converter/primitives.d.ts.map +0 -1
  489. package/dist/ir/type-converter/primitives.js.map +0 -1
  490. package/dist/ir/type-converter/references.d.ts.map +0 -1
  491. package/dist/ir/type-converter/references.js +0 -371
  492. package/dist/ir/type-converter/references.js.map +0 -1
  493. package/dist/ir/type-converter/unions-intersections.d.ts +0 -14
  494. package/dist/ir/type-converter/unions-intersections.d.ts.map +0 -1
  495. package/dist/ir/type-converter/unions-intersections.js +0 -22
  496. package/dist/ir/type-converter/unions-intersections.js.map +0 -1
  497. package/dist/ir/type-converter/utility-types.d.ts.map +0 -1
  498. package/dist/ir/type-converter/utility-types.js +0 -528
  499. package/dist/ir/type-converter/utility-types.js.map +0 -1
  500. package/dist/ir/type-converter/utility-types.test.d.ts.map +0 -1
  501. package/dist/ir/type-converter/utility-types.test.js.map +0 -1
  502. package/dist/ir/type-converter.d.ts +0 -6
  503. package/dist/ir/type-converter.d.ts.map +0 -1
  504. package/dist/ir/type-converter.js +0 -6
  505. package/dist/ir/type-converter.js.map +0 -1
  506. /package/dist/ir/{type-converter → type-system/internal/type-converter}/literals.js +0 -0
  507. /package/dist/ir/{type-converter → type-system/internal/type-converter}/utility-types.test.d.ts +0 -0
@@ -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
- return { program, checker, sourceFile };
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, checker) => {
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, checker)),
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 { checker, sourceFile } = createTestProgram(source);
128
+ const { binding, sourceFile } = createTestProgram(source);
117
129
  const typeRef = findTypeAliasReference(sourceFile, "PartialWithIndex");
118
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
142
+ const { binding, sourceFile } = createTestProgram(source);
131
143
  const typeRef = findTypeAliasReference(sourceFile, "ReadonlyWithIndex");
132
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
156
+ const { binding, sourceFile } = createTestProgram(source);
145
157
  const typeRef = findTypeAliasReference(sourceFile, "PartialPerson");
146
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
199
+ const { binding, sourceFile } = createTestProgram(source);
188
200
  const typeRef = findTypeAliasReference(sourceFile, "PartialWithUndefined");
189
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
222
+ const { binding, sourceFile } = createTestProgram(source);
211
223
  const typeRef = findTypeAliasReference(sourceFile, "PartialWithSynthetic");
212
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
246
+ const { binding, sourceFile } = createTestProgram(source);
235
247
  const typeRef = findTypeAliasReference(sourceFile, "PartialRequired");
236
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
267
+ const { binding, sourceFile } = createTestProgram(source);
256
268
  const typeRef = findTypeAliasReference(sourceFile, "PartialReadonly");
257
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
288
+ const { binding, sourceFile } = createTestProgram(source);
277
289
  const typeRef = findTypeAliasReference(sourceFile, "ReadonlyPartial");
278
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Readonly", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
311
+ const { binding, sourceFile } = createTestProgram(source);
300
312
  const typeRef = findTypeAliasReference(sourceFile, "PartialWithMethod");
301
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Partial", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
338
+ const { binding, sourceFile } = createTestProgram(source);
327
339
  const typeRef = findTypeAliasReference(sourceFile, "ContactInfo");
328
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Pick", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
363
+ const { binding, sourceFile } = createTestProgram(source);
352
364
  const typeRef = findTypeAliasReference(sourceFile, "MinimalPerson");
353
- const result = expandUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Omit", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
652
+ const { binding, sourceFile } = createTestProgram(source);
397
653
  const typeRef = findTypeAliasReference(sourceFile, "Result");
398
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
665
+ const { binding, sourceFile } = createTestProgram(source);
410
666
  const typeRef = findTypeAliasReference(sourceFile, "Result");
411
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
678
+ const { binding, sourceFile } = createTestProgram(source);
423
679
  const typeRef = findTypeAliasReference(sourceFile, "Result");
424
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
688
+ const { binding, sourceFile } = createTestProgram(source);
433
689
  const typeRef = findTypeAliasReference(sourceFile, "Result");
434
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
698
+ const { binding, sourceFile } = createTestProgram(source);
443
699
  const typeRef = findTypeAliasReference(sourceFile, "Result");
444
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "NonNullable", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
728
+ const { binding, sourceFile } = createTestProgram(source);
473
729
  const typeRef = findTypeAliasReference(sourceFile, "Result");
474
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
740
+ const { binding, sourceFile } = createTestProgram(source);
485
741
  const typeRef = findTypeAliasReference(sourceFile, "Result");
486
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
753
+ const { binding, sourceFile } = createTestProgram(source);
498
754
  const typeRef = findTypeAliasReference(sourceFile, "Result");
499
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
783
+ const { binding, sourceFile } = createTestProgram(source);
528
784
  const typeRef = findTypeAliasReference(sourceFile, "Result");
529
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
793
+ const { binding, sourceFile } = createTestProgram(source);
538
794
  const typeRef = findTypeAliasReference(sourceFile, "Result");
539
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
806
+ const { binding, sourceFile } = createTestProgram(source);
551
807
  const typeRef = findTypeAliasReference(sourceFile, "Result");
552
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
818
+ const { binding, sourceFile } = createTestProgram(source);
563
819
  const typeRef = findTypeAliasReference(sourceFile, "Result");
564
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
828
+ const { binding, sourceFile } = createTestProgram(source);
573
829
  const typeRef = findTypeAliasReference(sourceFile, "Result");
574
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
838
+ const { binding, sourceFile } = createTestProgram(source);
583
839
  const typeRef = findTypeAliasReference(sourceFile, "Result");
584
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
848
+ const { binding, sourceFile } = createTestProgram(source);
593
849
  const typeRef = findTypeAliasReference(sourceFile, "Result");
594
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
858
+ const { binding, sourceFile } = createTestProgram(source);
603
859
  const typeRef = findTypeAliasReference(sourceFile, "Result");
604
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
870
+ const { binding, sourceFile } = createTestProgram(source);
615
871
  const typeRef = findTypeAliasReference(sourceFile, "OnlyNumbers");
616
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
891
+ const { binding, sourceFile } = createTestProgram(source);
629
892
  const typeRef = findTypeAliasReference(sourceFile, "OnlyStrings");
630
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Extract", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
910
+ const { binding, sourceFile } = createTestProgram(source);
641
911
  const typeRef = findTypeAliasReference(sourceFile, "Result");
642
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Exclude", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
925
+ const { binding, sourceFile } = createTestProgram(source);
656
926
  const typeRef = findTypeAliasReference(sourceFile, "Result");
657
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
938
+ const { binding, sourceFile } = createTestProgram(source);
669
939
  const typeRef = findTypeAliasReference(sourceFile, "Result");
670
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
951
+ const { binding, sourceFile } = createTestProgram(source);
682
952
  const typeRef = findTypeAliasReference(sourceFile, "Result");
683
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
963
+ const { binding, sourceFile } = createTestProgram(source);
694
964
  const typeRef = findTypeAliasReference(sourceFile, "Result");
695
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1004
+ const { binding, sourceFile } = createTestProgram(source);
728
1005
  const typeRef = findTypeAliasReference(sourceFile, "Result");
729
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "ReturnType", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1019
+ const { binding, sourceFile } = createTestProgram(source);
743
1020
  const typeRef = findTypeAliasReference(sourceFile, "Result");
744
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1040
+ const { binding, sourceFile } = createTestProgram(source);
764
1041
  const typeRef = findTypeAliasReference(sourceFile, "Result");
765
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1073
+ const { binding, sourceFile } = createTestProgram(source);
797
1074
  const typeRef = findTypeAliasReference(sourceFile, "Result");
798
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Parameters", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1084
+ const { binding, sourceFile } = createTestProgram(source);
808
1085
  const typeRef = findTypeAliasReference(sourceFile, "Result");
809
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1097
+ const { binding, sourceFile } = createTestProgram(source);
821
1098
  const typeRef = findTypeAliasReference(sourceFile, "Result");
822
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1110
+ const { binding, sourceFile } = createTestProgram(source);
834
1111
  const typeRef = findTypeAliasReference(sourceFile, "Result");
835
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1123
+ const { binding, sourceFile } = createTestProgram(source);
847
1124
  const typeRef = findTypeAliasReference(sourceFile, "Result");
848
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1154
+ const { binding, sourceFile } = createTestProgram(source);
878
1155
  const typeRef = findTypeAliasReference(sourceFile, "Result");
879
- const result = expandConditionalUtilityType(assertDefined(typeRef, "typeRef should be defined"), "Awaited", checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1171
+ const { binding, sourceFile } = createTestProgram(source);
895
1172
  const typeRef = findTypeAliasReference(sourceFile, "Config");
896
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1187
+ const { binding, sourceFile } = createTestProgram(source);
911
1188
  const typeRef = findTypeAliasReference(sourceFile, "IndexedConfig");
912
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1204
+ const { binding, sourceFile } = createTestProgram(source);
928
1205
  const typeRef = findTypeAliasReference(sourceFile, "MixedConfig");
929
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1217
+ const { binding, sourceFile } = createTestProgram(source);
941
1218
  const typeRef = findTypeAliasReference(sourceFile, "Dictionary");
942
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1227
+ const { binding, sourceFile } = createTestProgram(source);
951
1228
  const typeRef = findTypeAliasReference(sourceFile, "NumberDictionary");
952
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
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"), checker, stubConvertType);
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 { checker, sourceFile } = createTestProgram(source);
1261
+ const { binding, sourceFile } = createTestProgram(source);
985
1262
  const typeRef = findTypeAliasReference(sourceFile, "AnyKeyRecord");
986
- const result = expandRecordType(assertDefined(typeRef, "typeRef should be defined"), checker, stubConvertType);
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);