goscript 0.0.47 → 0.0.49

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 (152) hide show
  1. package/cmd/goscript/deps.go +1 -4
  2. package/compiler/analysis.go +224 -63
  3. package/compiler/analysis_test.go +112 -0
  4. package/compiler/compiler.go +19 -87
  5. package/compiler/expr-call-type-conversion.go +148 -59
  6. package/compiler/expr-call.go +202 -10
  7. package/compiler/expr.go +5 -82
  8. package/compiler/gs_dependencies_test.go +60 -1
  9. package/compiler/spec-value.go +73 -51
  10. package/compiler/spec.go +293 -151
  11. package/compiler/stmt.go +192 -81
  12. package/dist/gs/builtin/builtin.d.ts +1 -5
  13. package/dist/gs/builtin/builtin.js +1 -34
  14. package/dist/gs/builtin/builtin.js.map +1 -1
  15. package/dist/gs/builtin/slice.js.map +1 -1
  16. package/dist/gs/fmt/fmt.js +20 -4
  17. package/dist/gs/fmt/fmt.js.map +1 -1
  18. package/dist/gs/io/fs/fs.d.ts +6 -12
  19. package/dist/gs/io/fs/fs.js +52 -67
  20. package/dist/gs/io/fs/fs.js.map +1 -1
  21. package/dist/gs/os/index.d.ts +2 -1
  22. package/dist/gs/os/index.js +1 -1
  23. package/dist/gs/os/index.js.map +1 -1
  24. package/dist/gs/os/types_js.gs.d.ts +7 -1
  25. package/dist/gs/os/types_js.gs.js +16 -1
  26. package/dist/gs/os/types_js.gs.js.map +1 -1
  27. package/dist/gs/os/types_unix.gs.js +2 -2
  28. package/dist/gs/os/types_unix.gs.js.map +1 -1
  29. package/dist/gs/reflect/index.d.ts +3 -3
  30. package/dist/gs/reflect/index.js +2 -2
  31. package/dist/gs/reflect/index.js.map +1 -1
  32. package/dist/gs/reflect/map.js +2 -2
  33. package/dist/gs/reflect/map.js.map +1 -1
  34. package/dist/gs/reflect/type.d.ts +8 -9
  35. package/dist/gs/reflect/type.js +101 -103
  36. package/dist/gs/reflect/type.js.map +1 -1
  37. package/dist/gs/reflect/types.d.ts +1 -10
  38. package/dist/gs/reflect/types.js +3 -26
  39. package/dist/gs/reflect/types.js.map +1 -1
  40. package/dist/gs/reflect/value.js +23 -23
  41. package/dist/gs/reflect/value.js.map +1 -1
  42. package/dist/gs/reflect/visiblefields.js +3 -3
  43. package/dist/gs/reflect/visiblefields.js.map +1 -1
  44. package/dist/gs/time/time.d.ts +11 -22
  45. package/dist/gs/time/time.js +29 -57
  46. package/dist/gs/time/time.js.map +1 -1
  47. package/gs/TODO.md +129 -0
  48. package/gs/builtin/builtin.ts +3 -41
  49. package/gs/builtin/slice.ts +1 -1
  50. package/gs/bytes/meta.json +10 -0
  51. package/gs/fmt/fmt.ts +18 -4
  52. package/gs/fmt/meta.json +5 -0
  53. package/gs/internal/meta.json +5 -0
  54. package/gs/io/fs/fs.ts +58 -73
  55. package/gs/io/meta.json +9 -0
  56. package/gs/maps/meta.json +6 -0
  57. package/gs/math/meta.json +5 -0
  58. package/gs/os/index.ts +8 -1
  59. package/gs/os/meta.json +15 -0
  60. package/gs/os/types_js.gs.ts +22 -1
  61. package/gs/os/types_unix.gs.ts +2 -2
  62. package/gs/path/meta.json +6 -0
  63. package/gs/reflect/function-types.test.ts +10 -10
  64. package/gs/reflect/index.ts +6 -6
  65. package/gs/reflect/map.ts +2 -2
  66. package/gs/reflect/meta.json +5 -0
  67. package/gs/reflect/type.ts +108 -103
  68. package/gs/reflect/types.ts +2 -28
  69. package/gs/reflect/value.ts +23 -23
  70. package/gs/reflect/visiblefields.ts +3 -3
  71. package/gs/strconv/meta.json +5 -0
  72. package/gs/strings/meta.json +9 -0
  73. package/gs/sync/meta.json +19 -0
  74. package/gs/time/time.ts +32 -65
  75. package/package.json +1 -1
  76. package/dist/gs/builtin/io.d.ts +0 -16
  77. package/dist/gs/builtin/io.js +0 -15
  78. package/dist/gs/builtin/io.js.map +0 -1
  79. package/dist/gs/internal/testlog/index.d.ts +0 -1
  80. package/dist/gs/internal/testlog/index.js +0 -5
  81. package/dist/gs/internal/testlog/index.js.map +0 -1
  82. package/dist/gs/maps/iter.gs.d.ts +0 -7
  83. package/dist/gs/maps/iter.gs.js +0 -65
  84. package/dist/gs/maps/iter.gs.js.map +0 -1
  85. package/dist/gs/maps/maps.gs.d.ts +0 -7
  86. package/dist/gs/maps/maps.gs.js +0 -79
  87. package/dist/gs/maps/maps.gs.js.map +0 -1
  88. package/dist/gs/reflect/abi.d.ts +0 -59
  89. package/dist/gs/reflect/abi.gs.d.ts +0 -59
  90. package/dist/gs/reflect/abi.gs.js +0 -79
  91. package/dist/gs/reflect/abi.gs.js.map +0 -1
  92. package/dist/gs/reflect/abi.js +0 -79
  93. package/dist/gs/reflect/abi.js.map +0 -1
  94. package/dist/gs/reflect/badlinkname.d.ts +0 -52
  95. package/dist/gs/reflect/badlinkname.gs.d.ts +0 -52
  96. package/dist/gs/reflect/badlinkname.gs.js +0 -72
  97. package/dist/gs/reflect/badlinkname.gs.js.map +0 -1
  98. package/dist/gs/reflect/badlinkname.js +0 -72
  99. package/dist/gs/reflect/badlinkname.js.map +0 -1
  100. package/dist/gs/reflect/deepequal.gs.d.ts +0 -25
  101. package/dist/gs/reflect/deepequal.gs.js +0 -308
  102. package/dist/gs/reflect/deepequal.gs.js.map +0 -1
  103. package/dist/gs/reflect/float32reg_generic.gs.d.ts +0 -2
  104. package/dist/gs/reflect/float32reg_generic.gs.js +0 -10
  105. package/dist/gs/reflect/float32reg_generic.gs.js.map +0 -1
  106. package/dist/gs/reflect/index.gs.d.ts +0 -1
  107. package/dist/gs/reflect/index.gs.js +0 -3
  108. package/dist/gs/reflect/index.gs.js.map +0 -1
  109. package/dist/gs/reflect/iter.gs.d.ts +0 -3
  110. package/dist/gs/reflect/iter.gs.js +0 -24
  111. package/dist/gs/reflect/iter.gs.js.map +0 -1
  112. package/dist/gs/reflect/makefunc.gs.d.ts +0 -34
  113. package/dist/gs/reflect/makefunc.gs.js +0 -288
  114. package/dist/gs/reflect/makefunc.gs.js.map +0 -1
  115. package/dist/gs/reflect/map_swiss.gs.d.ts +0 -14
  116. package/dist/gs/reflect/map_swiss.gs.js +0 -70
  117. package/dist/gs/reflect/map_swiss.gs.js.map +0 -1
  118. package/dist/gs/reflect/reflect.gs.d.ts +0 -132
  119. package/dist/gs/reflect/reflect.gs.js +0 -437
  120. package/dist/gs/reflect/reflect.gs.js.map +0 -1
  121. package/dist/gs/reflect/swapper.gs.d.ts +0 -1
  122. package/dist/gs/reflect/swapper.gs.js +0 -32
  123. package/dist/gs/reflect/swapper.gs.js.map +0 -1
  124. package/dist/gs/reflect/type.gs.d.ts +0 -4
  125. package/dist/gs/reflect/type.gs.js +0 -21
  126. package/dist/gs/reflect/type.gs.js.map +0 -1
  127. package/dist/gs/reflect/value.gs.d.ts +0 -4
  128. package/dist/gs/reflect/value.gs.js +0 -12
  129. package/dist/gs/reflect/value.gs.js.map +0 -1
  130. package/dist/gs/reflect/visiblefields.gs.d.ts +0 -3
  131. package/dist/gs/reflect/visiblefields.gs.js +0 -123
  132. package/dist/gs/reflect/visiblefields.gs.js.map +0 -1
  133. package/dist/gs/stringslite/index.d.ts +0 -1
  134. package/dist/gs/stringslite/index.js +0 -2
  135. package/dist/gs/stringslite/index.js.map +0 -1
  136. package/dist/gs/stringslite/strings.d.ts +0 -11
  137. package/dist/gs/stringslite/strings.js +0 -67
  138. package/dist/gs/stringslite/strings.js.map +0 -1
  139. package/gs/bytes/metadata.go +0 -12
  140. package/gs/fmt/metadata.go +0 -7
  141. package/gs/internal/metadata.go +0 -7
  142. package/gs/io/io.go +0 -75
  143. package/gs/io/metadata.go +0 -11
  144. package/gs/maps/metadata.go +0 -8
  145. package/gs/math/metadata.go +0 -7
  146. package/gs/os/metadata.go +0 -17
  147. package/gs/path/metadata.go +0 -8
  148. package/gs/reflect/metadata.go +0 -7
  149. package/gs/strconv/metadata.go +0 -7
  150. package/gs/strings/metadata.go +0 -11
  151. package/gs/sync/metadata.go +0 -7
  152. package/gs/sync/sync.go +0 -64
package/compiler/spec.go CHANGED
@@ -92,123 +92,196 @@ func (c *GoToTSCompiler) writeVarRefedFieldInitializer(fieldName string, fieldTy
92
92
  c.tsw.WriteLiterally(": $.varRef(")
93
93
 
94
94
  if isEmbedded {
95
- _, isPtr := fieldType.(*types.Pointer)
96
- _, isInterface := fieldType.Underlying().(*types.Interface)
97
- if isPtr || isInterface {
98
- c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
99
- } else {
100
- // Check if the embedded type is an interface
101
- embeddedTypeUnderlying := fieldType
102
- if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
103
- embeddedTypeUnderlying = named.Underlying()
104
- }
105
- if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
106
- // For interfaces, use the provided value or null instead of trying to instantiate
107
- c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
108
- } else {
109
- // For structs, instantiate with provided fields
110
- typeForNew := fieldName
111
- c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
112
- }
113
- }
95
+ c.writeEmbeddedFieldInitializer(fieldName, fieldType)
114
96
  } else {
115
- isStructValueType := false
116
- var structTypeNameForClone string
117
- if named, ok := fieldType.(*types.Named); ok {
118
- if _, isStruct := named.Underlying().(*types.Struct); isStruct {
119
- isStructValueType = true
120
- structTypeNameForClone = c.getTypeString(fieldType)
121
- }
122
- }
123
-
124
- if isStructValueType {
125
- c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
126
- } else {
127
- c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
128
- // Check if this is a named type or type alias and use constructor instead of null
129
- if named, isNamed := fieldType.(*types.Named); isNamed {
130
- // This is a named type
131
- // Check if underlying type is an interface
132
- if _, isInterface := named.Underlying().(*types.Interface); isInterface {
133
- // For interfaces, use null as the zero value
134
- c.tsw.WriteLiterally("null")
135
- } else if _, isStruct := named.Underlying().(*types.Struct); !isStruct {
136
- // For non-struct, non-interface named types, use constructor
137
- c.tsw.WriteLiterally("new ")
138
- c.WriteNamedType(named)
139
- c.tsw.WriteLiterally("(")
140
- c.WriteZeroValueForType(named.Underlying())
141
- c.tsw.WriteLiterally(")")
142
- } else {
143
- c.WriteZeroValueForType(fieldType)
144
- }
145
- } else if alias, isAlias := fieldType.(*types.Alias); isAlias {
146
- // This is a type alias (like os.FileMode)
147
- // Check if underlying type is an interface
148
- if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
149
- // For interface type aliases, use null as the zero value
150
- c.tsw.WriteLiterally("null")
151
- } else if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
152
- // For non-struct, non-interface type aliases, use constructor
153
- c.tsw.WriteLiterally("new ")
154
- // Use AST type information if available to preserve qualified names
155
- if astType != nil {
156
- c.WriteTypeExpr(astType)
157
- } else {
158
- c.WriteGoType(fieldType, GoTypeContextGeneral)
159
- }
160
- c.tsw.WriteLiterally("(")
161
- c.WriteZeroValueForType(alias.Underlying())
162
- c.tsw.WriteLiterally(")")
163
- } else {
164
- c.WriteZeroValueForType(fieldType)
165
- }
166
- } else {
167
- c.WriteZeroValueForType(fieldType)
168
- }
169
- }
97
+ c.writeRegularFieldInitializer(fieldName, fieldType, astType)
170
98
  }
171
99
 
172
100
  c.tsw.WriteLiterally(")")
173
101
  }
174
102
 
175
- func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
176
- c.tsw.WriteLiterally(fieldName)
177
- c.tsw.WriteLiterally(": $.varRef(")
103
+ func (c *GoToTSCompiler) writeEmbeddedFieldInitializer(fieldName string, fieldType types.Type) {
104
+ _, isPtr := fieldType.(*types.Pointer)
105
+ _, isInterface := fieldType.Underlying().(*types.Interface)
178
106
 
179
- if isEmbedded {
180
- isPointerToStruct := false
181
- trueType := fieldType
182
- if ptr, isPtr := trueType.(*types.Pointer); isPtr {
183
- trueType = ptr.Elem()
184
- isPointerToStruct = true
185
- }
107
+ if isPtr || isInterface {
108
+ c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
109
+ return
110
+ }
186
111
 
187
- if named, isNamed := trueType.(*types.Named); isNamed {
188
- _, isUnderlyingStruct := named.Underlying().(*types.Struct)
189
- if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
190
- c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
191
- } else { // Is a pointer to a struct, or not a struct
192
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
112
+ // Check if the embedded type is an interface
113
+ embeddedTypeUnderlying := fieldType
114
+ if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
115
+ embeddedTypeUnderlying = named.Underlying()
116
+ }
117
+
118
+ if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
119
+ // For interfaces, use the provided value or null instead of trying to instantiate
120
+ c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
121
+ return
122
+ }
123
+
124
+ // For structs, instantiate with provided fields
125
+ typeForNew := fieldName
126
+ c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
127
+ }
128
+
129
+ func (c *GoToTSCompiler) writeRegularFieldInitializer(fieldName string, fieldType types.Type, astType ast.Expr) {
130
+ // Check if this is a struct value type that needs cloning
131
+ if c.isStructValueType(fieldType) {
132
+ structTypeNameForClone := c.getTypeString(fieldType)
133
+ c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
134
+ return
135
+ }
136
+
137
+ c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
138
+
139
+ // Debugging: print field type info
140
+ if astType != nil {
141
+ if named, ok := fieldType.(*types.Named); ok {
142
+ if pkgPath := named.Obj().Pkg().Path(); pkgPath != "" {
143
+ c.tsw.WriteCommentLinef("DEBUG: Field %s has type %s (%T)", fieldName, fieldType, fieldType)
193
144
  }
194
145
  } else {
195
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
146
+ c.tsw.WriteCommentLinef("DEBUG: Field %s has type %s (%T)", fieldName, fieldType, fieldType)
196
147
  }
197
- } else {
198
- isValueTypeStruct := false
199
- if named, ok := fieldType.(*types.Named); ok {
200
- if _, isStruct := named.Underlying().(*types.Struct); isStruct {
201
- isValueTypeStruct = true
148
+ if typeName, ok := c.pkg.TypesInfo.TypeOf(astType).(*types.Named); ok {
149
+ pkgPath := ""
150
+ if typeName.Obj().Pkg() != nil {
151
+ pkgPath = typeName.Obj().Pkg().Path()
202
152
  }
153
+ c.tsw.WriteCommentLinef("DEBUG: Package=%s, TypeName=%s", pkgPath, typeName)
203
154
  }
155
+ }
204
156
 
205
- if isValueTypeStruct {
206
- c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
157
+ // Priority 1: Check if this is a wrapper type
158
+ if c.analysis.IsWrapperType(fieldType) {
159
+ c.tsw.WriteCommentLinef("DEBUG: Using wrapper type zero value")
160
+ // For wrapper types, use the zero value of the underlying type with type casting
161
+ if named, ok := fieldType.(*types.Named); ok {
162
+ c.WriteZeroValueForType(named.Underlying())
163
+ c.tsw.WriteLiterally(" as ")
164
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
165
+ } else if alias, ok := fieldType.(*types.Alias); ok {
166
+ c.WriteZeroValueForType(alias.Underlying())
167
+ c.tsw.WriteLiterally(" as ")
168
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
207
169
  } else {
208
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
170
+ // Fallback to original behavior
171
+ c.WriteZeroValueForType(fieldType)
209
172
  }
173
+ return
174
+ }
175
+
176
+ // Priority 2: Handle imported types with basic underlying types (like os.FileMode)
177
+ if c.isImportedBasicType(fieldType) {
178
+ c.tsw.WriteCommentLinef("DEBUG: Using imported basic type zero value")
179
+ c.writeImportedBasicTypeZeroValue(fieldType)
180
+ return
181
+ }
182
+
183
+ // Priority 3: Handle named types
184
+ if named, isNamed := fieldType.(*types.Named); isNamed {
185
+ c.tsw.WriteCommentLinef("DEBUG: Using named type zero value")
186
+ c.writeNamedTypeZeroValue(named)
187
+ return
188
+ }
189
+
190
+ // Priority 4: Handle type aliases
191
+ if alias, isAlias := fieldType.(*types.Alias); isAlias {
192
+ c.tsw.WriteCommentLinef("DEBUG: Using type alias zero value")
193
+ c.writeTypeAliasZeroValue(alias, astType)
194
+ return
195
+ }
196
+
197
+ // Default: use WriteZeroValueForType
198
+ c.tsw.WriteCommentLinef("DEBUG: Using default zero value")
199
+ c.WriteZeroValueForType(fieldType)
200
+ }
201
+
202
+ func (c *GoToTSCompiler) isStructValueType(fieldType types.Type) bool {
203
+ if named, ok := fieldType.(*types.Named); ok {
204
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
205
+ return true
206
+ }
207
+ }
208
+ return false
209
+ }
210
+
211
+ func (c *GoToTSCompiler) isImportedBasicType(fieldType types.Type) bool {
212
+ named, isNamed := fieldType.(*types.Named)
213
+ if !isNamed {
214
+ return false
215
+ }
216
+
217
+ obj := named.Obj()
218
+ if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
219
+ return false // Not imported or is local
220
+ }
221
+
222
+ underlying := named.Underlying()
223
+ if underlying == nil {
224
+ return false
210
225
  }
211
226
 
227
+ _, isBasic := underlying.(*types.Basic)
228
+ return isBasic
229
+ }
230
+
231
+ func (c *GoToTSCompiler) writeImportedBasicTypeZeroValue(fieldType types.Type) {
232
+ named := fieldType.(*types.Named)
233
+ underlying := named.Underlying()
234
+
235
+ // Write zero value of underlying type with type casting
236
+ c.WriteZeroValueForType(underlying)
237
+ c.tsw.WriteLiterally(" as ")
238
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
239
+ }
240
+
241
+ func (c *GoToTSCompiler) writeNamedTypeZeroValue(named *types.Named) {
242
+ // Check if underlying type is an interface
243
+ if _, isInterface := named.Underlying().(*types.Interface); isInterface {
244
+ c.tsw.WriteLiterally("null")
245
+ return
246
+ }
247
+
248
+ // Check if underlying type is a struct
249
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
250
+ c.WriteZeroValueForType(named)
251
+ return
252
+ }
253
+
254
+ // For non-struct, non-interface named types, use constructor
255
+ c.tsw.WriteLiterally("new ")
256
+ c.WriteNamedType(named)
257
+ c.tsw.WriteLiterally("(")
258
+ c.WriteZeroValueForType(named.Underlying())
259
+ c.tsw.WriteLiterally(")")
260
+ }
261
+
262
+ func (c *GoToTSCompiler) writeTypeAliasZeroValue(alias *types.Alias, astType ast.Expr) {
263
+ // Check if underlying type is an interface
264
+ if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
265
+ c.tsw.WriteLiterally("null")
266
+ return
267
+ }
268
+
269
+ // Check if underlying type is a struct
270
+ if _, isStruct := alias.Underlying().(*types.Struct); isStruct {
271
+ c.WriteZeroValueForType(alias)
272
+ return
273
+ }
274
+
275
+ // For non-struct, non-interface type aliases, use constructor
276
+ c.tsw.WriteLiterally("new ")
277
+ // Use AST type information if available to preserve qualified names
278
+ if astType != nil {
279
+ c.WriteTypeExpr(astType)
280
+ } else {
281
+ c.WriteGoType(alias, GoTypeContextGeneral)
282
+ }
283
+ c.tsw.WriteLiterally("(")
284
+ c.WriteZeroValueForType(alias.Underlying())
212
285
  c.tsw.WriteLiterally(")")
213
286
  }
214
287
 
@@ -244,7 +317,11 @@ func (c *GoToTSCompiler) hasReceiverMethods(typeName string) bool {
244
317
  return false
245
318
  }
246
319
 
247
- // WriteNamedTypeWithMethods generates a TypeScript class for a Go named type that has receiver methods
320
+ // WriteNamedTypeWithMethods generates TypeScript code for Go named types that have methods.
321
+ // Instead of generating a class, it now generates:
322
+ // 1. A type alias for the underlying type
323
+ // 2. Function declarations for each method (TypeName_MethodName)
324
+ // 3. Function implementations for each method
248
325
  func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
249
326
  className := a.Name.Name
250
327
 
@@ -258,49 +335,16 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
258
335
  c.tsw.WriteLiterally("export ")
259
336
  }
260
337
 
261
- c.tsw.WriteLiterallyf("class %s {", className)
262
- c.tsw.WriteLine("")
263
- c.tsw.Indent(1)
264
-
265
- // Constructor that takes the underlying type value
266
- c.tsw.WriteLiterally("constructor(private _value: ")
267
- // Use AST-based type writing to preserve qualified names like os.FileInfo
268
- c.WriteTypeExpr(a.Type)
269
- c.tsw.WriteLine(") {}")
270
- c.tsw.WriteLine("")
271
-
272
- // valueOf method to get the underlying value (for type conversions and operations)
273
- c.tsw.WriteLiterally("valueOf(): ")
274
- // Use AST-based type writing to preserve qualified names like os.FileInfo
275
- c.WriteTypeExpr(a.Type)
276
- c.tsw.WriteLine(" {")
277
- c.tsw.Indent(1)
278
- c.tsw.WriteLine("return this._value")
279
- c.tsw.Indent(-1)
280
- c.tsw.WriteLine("}")
281
- c.tsw.WriteLine("")
282
-
283
- // toString method for string conversion
284
- c.tsw.WriteLine("toString(): string {")
285
- c.tsw.Indent(1)
286
- c.tsw.WriteLine("return String(this._value)")
287
- c.tsw.Indent(-1)
288
- c.tsw.WriteLine("}")
289
- c.tsw.WriteLine("")
290
-
291
- // Static from method for type conversion
292
- c.tsw.WriteLiterallyf("static from(value: ")
338
+ // Generate type alias instead of class
339
+ c.tsw.WriteLiterally("type ")
340
+ c.tsw.WriteLiterally(className)
341
+ c.tsw.WriteLiterally(" = ")
293
342
  // Use AST-based type writing to preserve qualified names like os.FileInfo
294
343
  c.WriteTypeExpr(a.Type)
295
- c.tsw.WriteLiterallyf("): %s {", className)
296
- c.tsw.WriteLine("")
297
- c.tsw.Indent(1)
298
- c.tsw.WriteLiterallyf("return new %s(value)", className)
344
+ c.tsw.WriteLine(";")
299
345
  c.tsw.WriteLine("")
300
- c.tsw.Indent(-1)
301
- c.tsw.WriteLine("}")
302
346
 
303
- // Add receiver methods for this type
347
+ // Generate function declarations and implementations for each method
304
348
  for _, fileSyntax := range c.pkg.Syntax {
305
349
  for _, decl := range fileSyntax.Decls {
306
350
  funcDecl, isFunc := decl.(*ast.FuncDecl)
@@ -324,28 +368,86 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
324
368
  }
325
369
 
326
370
  if recvTypeName == className {
327
- c.tsw.WriteLine("")
328
- if err := c.writeNamedTypeMethod(funcDecl); err != nil {
371
+ if !isInsideFunction {
372
+ c.tsw.WriteLiterally("export ")
373
+ }
374
+
375
+ // Generate function signature: export function TypeName_MethodName(receiver: TypeName, ...args): ReturnType
376
+ c.tsw.WriteLiterally("function ")
377
+ c.tsw.WriteLiterally(className)
378
+ c.tsw.WriteLiterally("_")
379
+ c.tsw.WriteLiterally(funcDecl.Name.Name)
380
+ c.tsw.WriteLiterally("(")
381
+
382
+ // First parameter is the receiver - use the original receiver parameter name
383
+ var receiverParamName string = "receiver" // default fallback
384
+ if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
385
+ if len(funcDecl.Recv.List[0].Names) > 0 {
386
+ if name := funcDecl.Recv.List[0].Names[0]; name != nil && name.Name != "_" {
387
+ receiverParamName = name.Name
388
+ }
389
+ }
390
+ }
391
+ c.tsw.WriteLiterally(receiverParamName)
392
+ c.tsw.WriteLiterally(": ")
393
+ c.tsw.WriteLiterally(className)
394
+
395
+ // Add other parameters
396
+ if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) > 0 {
397
+ c.tsw.WriteLiterally(", ")
398
+ c.WriteFieldList(funcDecl.Type.Params, true) // true = arguments
399
+ }
400
+
401
+ c.tsw.WriteLiterally(")")
402
+
403
+ // Add return type
404
+ if funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) > 0 {
405
+ c.tsw.WriteLiterally(": ")
406
+ if len(funcDecl.Type.Results.List) == 1 {
407
+ c.WriteTypeExpr(funcDecl.Type.Results.List[0].Type)
408
+ } else {
409
+ c.tsw.WriteLiterally("[")
410
+ for i, field := range funcDecl.Type.Results.List {
411
+ if i > 0 {
412
+ c.tsw.WriteLiterally(", ")
413
+ }
414
+ c.WriteTypeExpr(field.Type)
415
+ }
416
+ c.tsw.WriteLiterally("]")
417
+ }
418
+ } else {
419
+ c.tsw.WriteLiterally(": void")
420
+ }
421
+
422
+ c.tsw.WriteLine(" {")
423
+ c.tsw.Indent(1)
424
+
425
+ // Write method body with receiver as first parameter
426
+ if err := c.writeWrapperFunctionBody(funcDecl, className); err != nil {
329
427
  return err
330
428
  }
429
+
430
+ c.tsw.Indent(-1)
431
+ c.tsw.WriteLine("}")
432
+ c.tsw.WriteLine("")
331
433
  }
332
434
  }
333
435
  }
334
436
 
335
- c.tsw.Indent(-1)
336
- c.tsw.WriteLine("}")
337
-
338
437
  return nil
339
438
  }
340
439
 
341
- // writeNamedTypeMethod writes a method for a named type, handling receiver binding properly
342
- func (c *GoToTSCompiler) writeNamedTypeMethod(decl *ast.FuncDecl) error {
343
- _, err := c.writeMethodSignature(decl)
344
- if err != nil {
345
- return err
440
+ // writeWrapperFunctionBody writes the body of a wrapper function, treating the receiver as the first parameter
441
+ func (c *GoToTSCompiler) writeWrapperFunctionBody(decl *ast.FuncDecl, typeName string) error {
442
+ // Write function body statements directly - identifier mapping is handled by pre-computed analysis
443
+ if decl.Body != nil {
444
+ for _, stmt := range decl.Body.List {
445
+ if err := c.WriteStmt(stmt); err != nil {
446
+ return err
447
+ }
448
+ }
346
449
  }
347
-
348
- return c.writeMethodBodyWithReceiverBinding(decl, "this._value")
450
+ return nil
349
451
  }
350
452
 
351
453
  // WriteTypeSpec writes the type specification to the output.
@@ -515,3 +617,43 @@ func (c *GoToTSCompiler) WriteImportSpec(a *ast.ImportSpec) {
515
617
 
516
618
  c.tsw.WriteImport(impName, tsImportPath+"/index.js")
517
619
  }
620
+
621
+ func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
622
+ c.tsw.WriteLiterally(fieldName)
623
+ c.tsw.WriteLiterally(": $.varRef(")
624
+
625
+ if isEmbedded {
626
+ isPointerToStruct := false
627
+ trueType := fieldType
628
+ if ptr, isPtr := trueType.(*types.Pointer); isPtr {
629
+ trueType = ptr.Elem()
630
+ isPointerToStruct = true
631
+ }
632
+
633
+ if named, isNamed := trueType.(*types.Named); isNamed {
634
+ _, isUnderlyingStruct := named.Underlying().(*types.Struct)
635
+ if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
636
+ c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
637
+ } else { // Is a pointer to a struct, or not a struct
638
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
639
+ }
640
+ } else {
641
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
642
+ }
643
+ } else {
644
+ isValueTypeStruct := false
645
+ if named, ok := fieldType.(*types.Named); ok {
646
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
647
+ isValueTypeStruct = true
648
+ }
649
+ }
650
+
651
+ if isValueTypeStruct {
652
+ c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
653
+ } else {
654
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
655
+ }
656
+ }
657
+
658
+ c.tsw.WriteLiterally(")")
659
+ }