You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,7 @@ This document contains guidelines and rules for AI agents working on the GoScrip
17
17
- Leverage adding more tests, for example in `compiler/analysis_test.go`, instead of debug logging, for diagnosing issues or investigating hypotheses. If the new test case is temporary and you plan to remove it later, add a `tmp_test.go` file or similar to keep things separated.
18
18
- AVOID type arguments unless necessary (prefer type inference)
19
19
- When making Git commits use the existing commit message pattern and Linux-kernel style commit message bodies.
20
+
- When you would normally add a new compliance test check if a very-similar compliance test already exists and if so extend that one instead. For example testing another function in the same package.
# Analysis: Untyped Struct Literals in Slice Literals
2
+
3
+
## Problem
4
+
5
+
When we have a slice literal like:
6
+
```go
7
+
people:= []Person{
8
+
{Name: "Charlie", Age: 30},
9
+
{Name: "Alice", Age: 25},
10
+
{Name: "Bob", Age: 35},
11
+
}
12
+
```
13
+
14
+
The generated TypeScript is:
15
+
```ts
16
+
let people =$.arrayToSlice<Person>([{Age: 30, Name: "Charlie"}, {Age: 25, Name: "Alice"}, {Age: 35, Name: "Bob"}])
17
+
```
18
+
19
+
This generates TypeScript type errors because `{Age: 30, Name: "Charlie"}` is a plain object literal, not a `Person` instance with `_fields` and `clone` methods.
20
+
21
+
## Root Cause
22
+
23
+
In `WriteCompositeLit`, when processing array elements at lines 184-186:
24
+
```go
25
+
ifelm, ok:= elements[i]; ok && elm != nil {
26
+
iferr:= c.WriteVarRefedValue(elm); err != nil {
27
+
return fmt.Errorf("failed to write array literal element: %w", err)
28
+
}
29
+
}
30
+
```
31
+
32
+
The elements are untyped composite literals (`{Name: "Charlie", Age: 30}`). When `WriteVarRefedValue` is called on these, it delegates to `WriteValueExpr`, which calls `WriteCompositeLit`.
33
+
34
+
Inside `WriteCompositeLit` for these untyped literals, the function checks if `exp.Type` is nil (line 334). Since these literals don't have an explicit type in the AST, it falls through to the untyped path starting at line 336.
35
+
36
+
The untyped path calls `writeUntypedStructLiteral` (line 387) which just creates a plain object literal `{...}` instead of calling the struct constructor.
37
+
38
+
## Solution
39
+
40
+
When we have an untyped struct literal, we need to check if the inferred type is a named struct type. If it is, we should generate `new StructName({...})` instead of just `{...}`.
41
+
42
+
The type information is available via `c.pkg.TypesInfo.Types[exp]` which gives us the inferred type.
43
+
44
+
## Fix
45
+
46
+
Modify `writeUntypedStructLiteral` to:
47
+
1. Check if the inferred type for the expression is a named struct type
48
+
2. If so, generate `new TypeName({...})` with the constructor call
49
+
3. If it's truly anonymous (no named type), keep the plain object literal
50
+
51
+
This requires checking the parent types.Type that led us to call writeUntypedStructLiteral.
0 commit comments