goscript 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/goscript/cmd_compile.go +2 -2
- package/compiler/analysis.go +229 -51
- package/compiler/assignment.go +412 -0
- package/compiler/compiler.go +185 -5885
- package/compiler/compiler_test.go +40 -8
- package/compiler/composite-lit.go +552 -0
- package/compiler/config.go +3 -0
- package/compiler/decl.go +259 -0
- package/compiler/expr-call.go +479 -0
- package/compiler/expr-selector.go +125 -0
- package/compiler/expr-star.go +90 -0
- package/compiler/expr-type.go +309 -0
- package/compiler/expr-value.go +89 -0
- package/compiler/expr.go +591 -0
- package/compiler/field.go +169 -0
- package/compiler/lit.go +131 -0
- package/compiler/primitive.go +148 -0
- package/compiler/{write-type-spec.go → spec-struct.go} +211 -204
- package/compiler/spec-value.go +226 -0
- package/compiler/spec.go +272 -0
- package/compiler/stmt-assign.go +439 -0
- package/compiler/stmt-for.go +178 -0
- package/compiler/stmt-range.go +235 -0
- package/compiler/stmt-select.go +211 -0
- package/compiler/stmt-type-switch.go +147 -0
- package/compiler/stmt.go +792 -0
- package/compiler/type-assert.go +209 -0
- package/compiler/type-info.go +141 -0
- package/compiler/type.go +618 -0
- package/go.mod +2 -1
- package/go.sum +4 -2
- package/package.json +6 -6
- package/builtin/builtin.go +0 -11
- package/builtin/builtin.ts +0 -2114
- package/dist/builtin/builtin.d.ts +0 -495
- package/dist/builtin/builtin.js +0 -1490
- package/dist/builtin/builtin.js.map +0 -1
- /package/compiler/{writer.go → code-writer.go} +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"go/ast"
|
|
6
|
+
"go/token"
|
|
7
|
+
"strings"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// writeTypeAssert handles the Go type assertion with comma-ok idiom in an
|
|
11
|
+
// assignment context: `value, ok := interfaceExpr.(AssertedType)` (or with `=`).
|
|
12
|
+
// It translates this to a TypeScript destructuring assignment (or declaration if `tok`
|
|
13
|
+
// is `token.DEFINE` for `:=`) using the `$.typeAssert` runtime helper.
|
|
14
|
+
//
|
|
15
|
+
// The generated TypeScript is:
|
|
16
|
+
// `[let] { value: valueName, ok: okName } = $.typeAssert<AssertedType_ts>(interfaceExpr_ts, 'AssertedTypeName');`
|
|
17
|
+
//
|
|
18
|
+
// - `AssertedType_ts` is the TypeScript translation of `AssertedType`.
|
|
19
|
+
// - `interfaceExpr_ts` is the TypeScript translation of `interfaceExpr`.
|
|
20
|
+
// - `'AssertedTypeName'` is a string representation of the asserted type name,
|
|
21
|
+
// obtained via `getTypeNameString`, used for runtime error messages.
|
|
22
|
+
// - `valueName` and `okName` are the Go variable names from the LHS.
|
|
23
|
+
// - Blank identifiers (`_`) on the LHS are handled by omitting the corresponding
|
|
24
|
+
// property in the destructuring pattern (e.g., `{ ok: okName } = ...` if `value` is blank).
|
|
25
|
+
// - If `tok` is not `token.DEFINE` (i.e., for regular assignment `=`), the entire
|
|
26
|
+
// destructuring assignment is wrapped in parentheses `(...)` to make it a valid
|
|
27
|
+
// expression if needed, though typically assignments are statements.
|
|
28
|
+
//
|
|
29
|
+
// The statement is terminated with a newline.
|
|
30
|
+
func (c *GoToTSCompiler) writeTypeAssert(lhs []ast.Expr, typeAssertExpr *ast.TypeAssertExpr, tok token.Token) error {
|
|
31
|
+
interfaceExpr := typeAssertExpr.X
|
|
32
|
+
assertedType := typeAssertExpr.Type
|
|
33
|
+
|
|
34
|
+
// Unwrap parenthesized expressions to handle cases like r.((<-chan T))
|
|
35
|
+
for {
|
|
36
|
+
if parenExpr, ok := assertedType.(*ast.ParenExpr); ok {
|
|
37
|
+
assertedType = parenExpr.X
|
|
38
|
+
} else {
|
|
39
|
+
break
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Ensure LHS has exactly two expressions (value and ok)
|
|
44
|
+
if len(lhs) != 2 {
|
|
45
|
+
return fmt.Errorf("type assertion assignment requires exactly 2 variables on LHS, got %d", len(lhs))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var okIsBlank bool
|
|
49
|
+
var okName string
|
|
50
|
+
|
|
51
|
+
okExpr := lhs[1]
|
|
52
|
+
okIdent, ok := okExpr.(*ast.Ident)
|
|
53
|
+
if !ok {
|
|
54
|
+
return fmt.Errorf("ok expression is not an identifier: %T", okExpr)
|
|
55
|
+
}
|
|
56
|
+
okIsBlank = okIdent.Name == "_"
|
|
57
|
+
okName = okIdent.Name
|
|
58
|
+
|
|
59
|
+
valueExpr := lhs[0]
|
|
60
|
+
|
|
61
|
+
// Determine if 'ok' variable is new in 'tok == token.DEFINE' context.
|
|
62
|
+
// This uses types.Info.Defs to see if the identifier is defined by this statement.
|
|
63
|
+
var okIsNewInDefine bool
|
|
64
|
+
if tok == token.DEFINE && !okIsBlank {
|
|
65
|
+
if c.pkg.TypesInfo.Defs[okIdent] != nil {
|
|
66
|
+
okIsNewInDefine = true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
switch vLHS := valueExpr.(type) {
|
|
71
|
+
case *ast.Ident:
|
|
72
|
+
var valueIsBlank bool
|
|
73
|
+
var valueName string
|
|
74
|
+
valueIdent := vLHS
|
|
75
|
+
valueIsBlank = (valueIdent.Name == "_")
|
|
76
|
+
valueName = valueIdent.Name
|
|
77
|
+
|
|
78
|
+
var valueIsNewInDefine bool
|
|
79
|
+
if tok == token.DEFINE && !valueIsBlank {
|
|
80
|
+
if c.pkg.TypesInfo.Defs[valueIdent] != nil { // valueIdent is defined by this statement
|
|
81
|
+
valueIsNewInDefine = true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
writeEndParen := false // For wrapping assignment in parens to make it an expression
|
|
86
|
+
letDestructure := false // True if 'let { value: v, ok: o } = ...' is appropriate
|
|
87
|
+
|
|
88
|
+
if tok == token.DEFINE {
|
|
89
|
+
anyNewVars := (valueIsNewInDefine && !valueIsBlank) || (okIsNewInDefine && !okIsBlank)
|
|
90
|
+
// allVarsNewOrBlank means suitable for a single `let {v,o} = ...` destructuring
|
|
91
|
+
allVarsNewOrBlank := (valueIsBlank || valueIsNewInDefine) && (okIsBlank || okIsNewInDefine)
|
|
92
|
+
|
|
93
|
+
if allVarsNewOrBlank && anyNewVars {
|
|
94
|
+
letDestructure = true
|
|
95
|
+
} else if anyNewVars { // Mixed: some new, some existing. Declare new ones separately.
|
|
96
|
+
if !valueIsBlank && valueIsNewInDefine {
|
|
97
|
+
c.tsw.WriteLiterally("let ")
|
|
98
|
+
c.tsw.WriteLiterally(valueName)
|
|
99
|
+
c.tsw.WriteLiterally(": ")
|
|
100
|
+
c.WriteTypeExpr(assertedType) // Use WriteTypeExpr for TS type annotation
|
|
101
|
+
c.tsw.WriteLine("")
|
|
102
|
+
}
|
|
103
|
+
if !okIsBlank && okIsNewInDefine {
|
|
104
|
+
c.tsw.WriteLiterally("let ")
|
|
105
|
+
c.tsw.WriteLiterally(okName)
|
|
106
|
+
c.tsw.WriteLiterally(": boolean")
|
|
107
|
+
c.tsw.WriteLine("")
|
|
108
|
+
}
|
|
109
|
+
c.tsw.WriteLiterally("(") // Parenthesize the assignment part
|
|
110
|
+
writeEndParen = true
|
|
111
|
+
} else { // All variables exist
|
|
112
|
+
c.tsw.WriteLiterally("(")
|
|
113
|
+
writeEndParen = true
|
|
114
|
+
}
|
|
115
|
+
} else { // tok == token.ASSIGN
|
|
116
|
+
c.tsw.WriteLiterally("(")
|
|
117
|
+
writeEndParen = true
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if letDestructure {
|
|
121
|
+
c.tsw.WriteLiterally("let ")
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Write the destructuring part: { value: v, ok: o }
|
|
125
|
+
c.tsw.WriteLiterally("{ ")
|
|
126
|
+
parts := []string{}
|
|
127
|
+
if !valueIsBlank {
|
|
128
|
+
parts = append(parts, fmt.Sprintf("value: %s", valueName))
|
|
129
|
+
}
|
|
130
|
+
if !okIsBlank {
|
|
131
|
+
parts = append(parts, fmt.Sprintf("ok: %s", okName))
|
|
132
|
+
}
|
|
133
|
+
c.tsw.WriteLiterally(strings.Join(parts, ", "))
|
|
134
|
+
c.tsw.WriteLiterally(" } = $.typeAssert<")
|
|
135
|
+
c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
|
|
136
|
+
c.tsw.WriteLiterally(">(")
|
|
137
|
+
if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
|
|
138
|
+
return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
|
|
139
|
+
}
|
|
140
|
+
c.tsw.WriteLiterally(", ")
|
|
141
|
+
c.writeTypeDescription(assertedType) // Arg2: type info for runtime
|
|
142
|
+
c.tsw.WriteLiterally(")")
|
|
143
|
+
|
|
144
|
+
if writeEndParen {
|
|
145
|
+
c.tsw.WriteLiterally(")")
|
|
146
|
+
}
|
|
147
|
+
c.tsw.WriteLine("")
|
|
148
|
+
|
|
149
|
+
case *ast.SelectorExpr:
|
|
150
|
+
// Handle s.field, ok := expr.(Type)
|
|
151
|
+
tempValName := "_gs_ta_val_" // Fixed name for temporary value
|
|
152
|
+
tempOkName := "_gs_ta_ok_" // Fixed name for temporary ok status
|
|
153
|
+
|
|
154
|
+
// Declare temporary variables:
|
|
155
|
+
// let _gs_ta_val_: AssertedTypeTS;
|
|
156
|
+
c.tsw.WriteLiterally("let ")
|
|
157
|
+
c.tsw.WriteLiterally(tempValName)
|
|
158
|
+
c.tsw.WriteLiterally(": ")
|
|
159
|
+
c.WriteTypeExpr(assertedType) // TypeScript type for assertedType
|
|
160
|
+
c.tsw.WriteLine("")
|
|
161
|
+
|
|
162
|
+
// let _gs_ta_ok_: boolean;
|
|
163
|
+
c.tsw.WriteLiterally("let ")
|
|
164
|
+
c.tsw.WriteLiterally(tempOkName)
|
|
165
|
+
c.tsw.WriteLiterally(": boolean")
|
|
166
|
+
c.tsw.WriteLine("")
|
|
167
|
+
|
|
168
|
+
// Perform type assertion into temporary variables:
|
|
169
|
+
// ({ value: _gs_ta_val_, ok: _gs_ta_ok_ } = $.typeAssert<AssertedTypeTS>(expr, "GoTypeStr"));
|
|
170
|
+
c.tsw.WriteLiterally("({ value: ")
|
|
171
|
+
c.tsw.WriteLiterally(tempValName)
|
|
172
|
+
c.tsw.WriteLiterally(", ok: ")
|
|
173
|
+
c.tsw.WriteLiterally(tempOkName)
|
|
174
|
+
c.tsw.WriteLiterally(" } = $.typeAssert<")
|
|
175
|
+
c.WriteTypeExpr(assertedType) // Generic: <AssertedTypeTS>
|
|
176
|
+
c.tsw.WriteLiterally(">(")
|
|
177
|
+
if err := c.WriteValueExpr(interfaceExpr); err != nil { // Arg1: interfaceExpr
|
|
178
|
+
return fmt.Errorf("failed to write interface expression in type assertion call: %w", err)
|
|
179
|
+
}
|
|
180
|
+
c.tsw.WriteLiterally(", ")
|
|
181
|
+
c.writeTypeDescription(assertedType) // Arg2: type info for runtime
|
|
182
|
+
c.tsw.WriteLine("))")
|
|
183
|
+
|
|
184
|
+
// Assign temporary value to the selector expression:
|
|
185
|
+
// s.f = _gs_ta_val_;
|
|
186
|
+
if err := c.WriteValueExpr(vLHS); err != nil { // Writes selector expression (e.g., "s.f")
|
|
187
|
+
return fmt.Errorf("failed to write LHS selector expression in type assertion: %w", err)
|
|
188
|
+
}
|
|
189
|
+
c.tsw.WriteLiterally(" = ")
|
|
190
|
+
c.tsw.WriteLiterally(tempValName)
|
|
191
|
+
c.tsw.WriteLine("")
|
|
192
|
+
|
|
193
|
+
// Assign temporary ok to the ok variable (e.g., okName = _gs_ta_ok_; or let okName = ...)
|
|
194
|
+
if !okIsBlank {
|
|
195
|
+
if okIsNewInDefine { // okIsNewInDefine was determined earlier based on tok == token.DEFINE and Defs check
|
|
196
|
+
c.tsw.WriteLiterally("let ")
|
|
197
|
+
}
|
|
198
|
+
c.tsw.WriteLiterally(okName)
|
|
199
|
+
c.tsw.WriteLiterally(" = ")
|
|
200
|
+
c.tsw.WriteLiterally(tempOkName)
|
|
201
|
+
c.tsw.WriteLine("")
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
default:
|
|
205
|
+
return fmt.Errorf("unhandled LHS expression type for value in type assertion: %T", valueExpr)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return nil
|
|
209
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import "go/types"
|
|
4
|
+
|
|
5
|
+
// writeTypeInfoObject writes a TypeScript TypeInfo object literal for a given Go type.
|
|
6
|
+
func (c *GoToTSCompiler) writeTypeInfoObject(typ types.Type) {
|
|
7
|
+
if typ == nil {
|
|
8
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Basic, name: 'any' }") // Or handle as error
|
|
9
|
+
return
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// If typ is a *types.Named, handle it by reference to break recursion.
|
|
13
|
+
if namedType, ok := typ.(*types.Named); ok {
|
|
14
|
+
if namedType.Obj().Name() == "error" && namedType.Obj().Pkg() == nil { // Check for builtin error
|
|
15
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Interface, name: 'GoError', methods: [{ name: 'Error', args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }] }] }")
|
|
16
|
+
} else {
|
|
17
|
+
// For all other named types, output their name as a string literal.
|
|
18
|
+
// This relies on the type being registered elsewhere (e.g., via registerStructType or registerInterfaceType)
|
|
19
|
+
// so the TypeScript runtime can resolve the reference.
|
|
20
|
+
c.tsw.WriteLiterallyf("%q", namedType.Obj().Name())
|
|
21
|
+
}
|
|
22
|
+
return // Return after handling the named type by reference.
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// If typ is not *types.Named, process its underlying structure.
|
|
26
|
+
underlying := typ.Underlying()
|
|
27
|
+
switch t := underlying.(type) {
|
|
28
|
+
case *types.Basic:
|
|
29
|
+
tsTypeName, _ := GoBuiltinToTypescript(t.Name())
|
|
30
|
+
if tsTypeName == "" {
|
|
31
|
+
tsTypeName = t.Name() // Fallback
|
|
32
|
+
}
|
|
33
|
+
c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Basic, name: %q }", tsTypeName)
|
|
34
|
+
// Note: The original 'case *types.Named:' here for 'underlying' is intentionally omitted.
|
|
35
|
+
// If typ.Underlying() is *types.Named (e.g. type T1 MyInt; type T2 T1;),
|
|
36
|
+
// then writeTypeInfoObject(typ.Underlying()) would be called in some contexts,
|
|
37
|
+
// and that call would handle it via the top-level *types.Named check.
|
|
38
|
+
case *types.Pointer:
|
|
39
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Pointer, elemType: ")
|
|
40
|
+
c.writeTypeInfoObject(t.Elem()) // Recursive call
|
|
41
|
+
c.tsw.WriteLiterally(" }")
|
|
42
|
+
case *types.Slice:
|
|
43
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Slice, elemType: ")
|
|
44
|
+
c.writeTypeInfoObject(t.Elem()) // Recursive call
|
|
45
|
+
c.tsw.WriteLiterally(" }")
|
|
46
|
+
case *types.Array:
|
|
47
|
+
c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Array, length: %d, elemType: ", t.Len())
|
|
48
|
+
c.writeTypeInfoObject(t.Elem()) // Recursive call
|
|
49
|
+
c.tsw.WriteLiterally(" }")
|
|
50
|
+
case *types.Map:
|
|
51
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Map, keyType: ")
|
|
52
|
+
c.writeTypeInfoObject(t.Key()) // Recursive call
|
|
53
|
+
c.tsw.WriteLiterally(", elemType: ")
|
|
54
|
+
c.writeTypeInfoObject(t.Elem()) // Recursive call
|
|
55
|
+
c.tsw.WriteLiterally(" }")
|
|
56
|
+
case *types.Chan:
|
|
57
|
+
dir := "both"
|
|
58
|
+
if t.Dir() == types.SendOnly {
|
|
59
|
+
dir = "send"
|
|
60
|
+
} else if t.Dir() == types.RecvOnly {
|
|
61
|
+
dir = "receive"
|
|
62
|
+
}
|
|
63
|
+
c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Channel, direction: %q, elemType: ", dir)
|
|
64
|
+
c.writeTypeInfoObject(t.Elem()) // Recursive call
|
|
65
|
+
c.tsw.WriteLiterally(" }")
|
|
66
|
+
case *types.Interface: // Anonymous interface or underlying of a non-named type alias
|
|
67
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Interface, methods: [")
|
|
68
|
+
var methods []*types.Func
|
|
69
|
+
for i := 0; i < t.NumExplicitMethods(); i++ {
|
|
70
|
+
methods = append(methods, t.ExplicitMethod(i))
|
|
71
|
+
}
|
|
72
|
+
// TODO: Handle embedded methods for anonymous interfaces if needed.
|
|
73
|
+
c.writeMethodSignatures(methods) // Calls writeMethodSignatures -> writeTypeInfoObject
|
|
74
|
+
c.tsw.WriteLiterally("] }")
|
|
75
|
+
case *types.Signature: // Anonymous func type or underlying of a non-named type alias
|
|
76
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Function, params: [")
|
|
77
|
+
for i := 0; i < t.Params().Len(); i++ {
|
|
78
|
+
if i > 0 {
|
|
79
|
+
c.tsw.WriteLiterally(", ")
|
|
80
|
+
}
|
|
81
|
+
c.writeTypeInfoObject(t.Params().At(i).Type()) // Recursive call
|
|
82
|
+
}
|
|
83
|
+
c.tsw.WriteLiterally("], results: [")
|
|
84
|
+
for i := 0; i < t.Results().Len(); i++ {
|
|
85
|
+
if i > 0 {
|
|
86
|
+
c.tsw.WriteLiterally(", ")
|
|
87
|
+
}
|
|
88
|
+
c.writeTypeInfoObject(t.Results().At(i).Type()) // Recursive call
|
|
89
|
+
}
|
|
90
|
+
c.tsw.WriteLiterally("] }")
|
|
91
|
+
case *types.Struct: // Anonymous struct or underlying of a non-named type alias
|
|
92
|
+
c.tsw.WriteLiterally("{ kind: $.TypeKind.Struct, fields: {")
|
|
93
|
+
for i := 0; i < t.NumFields(); i++ {
|
|
94
|
+
if i > 0 {
|
|
95
|
+
c.tsw.WriteLiterally(", ")
|
|
96
|
+
}
|
|
97
|
+
field := t.Field(i)
|
|
98
|
+
c.tsw.WriteLiterallyf("%q: ", field.Name())
|
|
99
|
+
c.writeTypeInfoObject(field.Type()) // Recursive call
|
|
100
|
+
}
|
|
101
|
+
c.tsw.WriteLiterally("}, methods: [] }") // Anonymous structs don't have methods in this context
|
|
102
|
+
default:
|
|
103
|
+
// Fallback, e.g. for types whose underlying isn't one of the above like *types.Tuple or other complex cases.
|
|
104
|
+
c.tsw.WriteLiterallyf("{ kind: $.TypeKind.Basic, name: %q }", typ.String()) // Fallback using the type's string representation
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// writeMethodSignatures writes an array of TypeScript MethodSignature objects.
|
|
109
|
+
func (c *GoToTSCompiler) writeMethodSignatures(methods []*types.Func) {
|
|
110
|
+
firstMethod := true
|
|
111
|
+
for _, method := range methods {
|
|
112
|
+
if !firstMethod {
|
|
113
|
+
c.tsw.WriteLiterally(", ")
|
|
114
|
+
}
|
|
115
|
+
firstMethod = false
|
|
116
|
+
|
|
117
|
+
sig := method.Type().(*types.Signature)
|
|
118
|
+
c.tsw.WriteLiterallyf("{ name: %q, args: [", method.Name())
|
|
119
|
+
for i := 0; i < sig.Params().Len(); i++ {
|
|
120
|
+
if i > 0 {
|
|
121
|
+
c.tsw.WriteLiterally(", ")
|
|
122
|
+
}
|
|
123
|
+
param := sig.Params().At(i)
|
|
124
|
+
c.tsw.WriteLiterallyf("{ name: %q, type: ", param.Name())
|
|
125
|
+
c.writeTypeInfoObject(param.Type())
|
|
126
|
+
c.tsw.WriteLiterally(" }")
|
|
127
|
+
}
|
|
128
|
+
c.tsw.WriteLiterally("], returns: [")
|
|
129
|
+
for i := 0; i < sig.Results().Len(); i++ {
|
|
130
|
+
if i > 0 {
|
|
131
|
+
c.tsw.WriteLiterally(", ")
|
|
132
|
+
}
|
|
133
|
+
result := sig.Results().At(i)
|
|
134
|
+
// Return parameters in Go often don't have names that are relevant for TS signature matching
|
|
135
|
+
c.tsw.WriteLiterally("{ type: ")
|
|
136
|
+
c.writeTypeInfoObject(result.Type())
|
|
137
|
+
c.tsw.WriteLiterally(" }")
|
|
138
|
+
}
|
|
139
|
+
c.tsw.WriteLiterally("] }")
|
|
140
|
+
}
|
|
141
|
+
}
|