@@ -71,12 +71,33 @@ const nullishString = z.string().nullish().transform(v => v ?? '');
7171const goString = z.string().nullish().transform(v => v ?? '');
7272```
7373
74+ ## Critical Thinking
75+
76+ **Do not blindly copy.** Before porting each function, type, or test, ask:
77+
78+ 1. **Does TypeScript need it?** Some Go code exists only because Go requires
79+ explicit opt-in for features that TypeScript provides natively. For example,
80+ Go requires an explicit `Unwrap() error` method for error chain traversal;
81+ TypeScript gets this for free via `Error.cause`. Do not port such code.
82+ 2. **Does the test validate our code or the language?** If a Go test verifies
83+ behaviour that is built into the TypeScript runtime (e.g. that `Error.cause`
84+ preserves a reference), skip it — it tests the language, not our
85+ implementation. Explain the skip to the user.
86+
87+ When in doubt, ask the user before porting.
88+
89+ ## Factory Functions vs Constructors
90+
91+ When a Go function can return `nil` (e.g. `FromHTTPError` returns `nil` for 2xx
92+ status codes), port it as a **factory function** that returns `T | undefined`.
93+ Constructors in TypeScript always return an instance and cannot express "no
94+ result." Use a standalone function or a static method on the class.
95+
7496## Tests
7597
76- Port **all** test cases from the Go SDK. Do not selectively skip tests. When a
77- Go test case cannot be directly ported (e.g. because of a language difference
78- like `json.RawMessage` vs already-parsed JSON), explain the omission to the
79- user and get confirmation before skipping.
98+ Port **all** test cases from the Go SDK unless they fall under the "Critical
99+ Thinking" exceptions above. Do not selectively skip tests without explaining
100+ the reason to the user.
80101
81102Use the same test structure as the Go SDK. Go table-driven tests map to
82103Vitest's `it.each`:
@@ -101,6 +122,22 @@ const testCases: {name: string; input: number; want: number}[] = [
101122it.each(testCases)('$name', ({input, want}) => { ... });
102123```
103124
125+ ## No Go References in Code
126+
127+ **Never reference Go in code or comments.** This includes variable names,
128+ function names, inline comments, and JSDoc. The TypeScript codebase must read
129+ as if Go does not exist. Do not write comments like "mirrors Go's
130+ tc.want.httpErr" or "equivalent of Go's errors.As."
131+
132+ ```typescript
133+ // Bad — references the Go implementation.
134+ // Input HTTP fields are always preserved (mirrors Go's
135+ // tc.want.httpErr = &httpError{statusCode, header, body}).
136+
137+ // Good — describes what the code does without referencing Go.
138+ // Input HTTP fields are always preserved.
139+ ```
140+
104141## Deviations from Go
105142
106143When the TypeScript implementation must differ from Go (e.g. different function
0 commit comments