typenative 0.0.19 → 0.0.20

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/CHANGELOG.md CHANGED
@@ -5,6 +5,33 @@ All notable changes to TypeNative will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.20] - 2026-03-16
9
+
10
+ ### Added
11
+
12
+ - **Spread in array literals**: `[...arr1, ...arr2]` → `append(append([]T{}, arr1...), arr2...)`
13
+ - **Rest parameters**: `function(...args: T[])` → Go variadic `func(...args T)`
14
+ - **Spread in function calls**: `fn(...args)` → `fn(args...)`
15
+ - **Array destructuring**: `const [a, b] = arr` → Go index assignments
16
+ - **Object shorthand**: `{ name }` → `{ name: name }` in struct literals
17
+ - **Static class members**: `static method()` / `static prop` → `ClassName_method()` / `ClassName_prop` package-level declarations; `ClassName.method()` calls correctly resolve
18
+ - **Getters/Setters**: `get prop()` → `Get_prop()` method, `set prop(v)` → `Set_prop(v)` method
19
+ - **`for...in` loops**: `for (const k in obj)` → `for k := range obj`
20
+ - **`Object.entries()` in `for...of`**: `for (const [k, v] of Object.entries(map))` unwraps to `for k, v := range map`
21
+ - **Named function expression IIFEs**: `(function name() { ... })()` → anonymous `func() { ... }()`
22
+ - **`process` global**: `process.argv` → `os.Args`, `process.platform` → `runtime.GOOS`, `process.exit()` → `os.Exit()`, `process.cwd()` → `os.Getwd()`
23
+ - **`JSON.stringify()` / `JSON.parse()`**: mapped to `encoding/json` `Marshal`/`Unmarshal`
24
+ - **`Object.keys()` / `Object.values()` / `Object.entries()`**: map iteration helpers
25
+ - **Array methods**: `findIndex`, `every`, `forEach`, `reduce`, `pop`, `shift`, `unshift`, `reverse`, `sort`, `concat`, `flat`, `at`
26
+ - **String methods**: `padStart`, `padEnd`, `match`, `matchAll`, `search`, `at`
27
+ - **Math methods**: `log`, `log2`, `log10`, `sin`, `cos`, `tan`, `trunc`, `sign`
28
+ - **`console.error()`**: maps to `fmt.Fprintln(os.Stderr, ...)`
29
+ - **`String()` / `Number()` / `Boolean()`** conversion functions
30
+ - **Go reserved words protection**: `getSafeName()` now covers all Go keywords (`break`, `case`, `chan`, `continue`, `default`, `defer`, `else`, `fallthrough`, `for`, `func`, `go`, `goto`, `if`, `import`, `interface`, `map`, `package`, `range`, `return`, `select`, `struct`, `switch`, `type`, `var`)
31
+ - **Default import namespaces from npm/local packages**: `import ts from 'typescript'` registers `ts` as a stripped namespace so `ts.method()` → `method()`
32
+ - **Better unsupported syntax warnings**: `console.warn` with syntax kind name and source snippet instead of `console.log`
33
+ - **Type definitions (`typenative.d.ts`)**: added `findIndex`, `every`, `forEach`, `reduce`, `pop`, `shift`, `unshift`, `reverse`, `sort`, `flat`, `concat`, `at` to `Array`; `padStart`, `padEnd`, `match`, `matchAll`, `search`, `at` to `String`; added `JSON`, `Object`, `Process`, extended `Math` and `Console`
34
+
8
35
  ## [0.0.19] - 2026-03-07
9
36
 
10
37
  ### Added
package/README.md CHANGED
@@ -29,10 +29,13 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
29
29
 
30
30
  **Variables & Objects**
31
31
 
32
- | Feature | Supported | Notes |
33
- | --------------------- | :-------: | -------------------------------- |
34
- | Variable declarations | ✅ | `let` and `const` |
35
- | Object literals | ✅ | Transpiled to Go struct literals |
32
+ | Feature | Supported | Notes |
33
+ | ---------------------- | :-------: | ----------------------------------------------- |
34
+ | Variable declarations | ✅ | `let` and `const` |
35
+ | Object literals | ✅ | Transpiled to Go struct literals |
36
+ | Object shorthand | ✅ | `{ name }` → `{ name: name }` |
37
+ | Array destructuring | ✅ | `const [a, b] = arr` |
38
+ | Object destructuring | ✅ | `const { x, y } = obj` |
36
39
 
37
40
  **Operators**
38
41
 
@@ -42,6 +45,7 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
42
45
  | Comparison operators | ✅ | `==`, `!=`, `===`, `!==`, etc. |
43
46
  | Logical operators | ✅ | `&&`, `\|\|` |
44
47
  | Increment/Decrement | ✅ | `++`, `--` |
48
+ | Spread operator | ✅ | `[...arr]`, `fn(...args)` |
45
49
  | Non-null assertion (`!`) | ✅ | Stripped during transpilation |
46
50
  | Ternary expressions | ✅ | `condition ? a : b` |
47
51
  | Nullish coalescing | ✅ | `??` operator |
@@ -54,21 +58,22 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
54
58
  | If/Else statements | ✅ | Fully supported |
55
59
  | Switch statements | ✅ | Case and default statements |
56
60
  | For loops | ✅ | Standard `for` loops |
57
- | For...of loops | ✅ | Iteration over arrays |
61
+ | For...of loops | ✅ | Arrays, Maps, Sets; `Object.entries()` unwrapping |
62
+ | For...in loops | ✅ | Iterates keys via Go `range` |
58
63
  | While loops | ✅ | Transpiled to Go's `for` loops |
59
64
  | Do...while loops | ✅ | Implemented with conditional break |
60
65
  | Try/Catch/Finally | ✅ | `throw` → `panic`; catch/finally via `defer`/`recover` |
61
66
 
62
67
  **Data Structures & Array Methods**
63
68
 
64
- | Feature | Supported | Notes |
65
- | -------------------------- | :-------: | ------------------------------------------------------------------------------------------ |
66
- | Arrays | ✅ | Basic array operations |
67
- | Array methods | ✅ | `push`, `join`, `slice` |
68
- | Higher-order array methods | ✅ | `.map()`, `.filter()`, `.some()`, `.find()` |
69
- | Method chaining | ✅ | Chaining array methods such as `.map(...).filter(...).join(...)` |
70
- | Map | ✅ | `Map<K, V>` → Go `map[K]V`; `.set()`, `.get()`, `.has()`, `.delete()`, `.clear()`, `.size` |
71
- | Set | ✅ | `Set<T>` → Go `map[T]struct{}`; `.add()`, `.has()`, `.delete()`, `.clear()`, `.size` |
69
+ | Feature | Supported | Notes |
70
+ | -------------------------- | :-------: | --------------------------------------------------------------------------------------------- |
71
+ | Arrays | ✅ | Basic array operations |
72
+ | Array methods | ✅ | `push`, `pop`, `shift`, `unshift`, `join`, `slice`, `concat`, `reverse`, `sort`, `flat`, `at` |
73
+ | Higher-order array methods | ✅ | `.map()`, `.filter()`, `.some()`, `.find()`, `.findIndex()`, `.every()`, `.forEach()`, `.reduce()` |
74
+ | Method chaining | ✅ | e.g. `.map(...).filter(...).join(...)` |
75
+ | Map | ✅ | `Map<K, V>` → Go `map[K]V`; `.set()`, `.get()`, `.has()`, `.delete()`, `.clear()`, `.size` |
76
+ | Set | ✅ | `Set<T>` → Go `map[T]struct{}`; `.add()`, `.has()`, `.delete()`, `.clear()`, `.size` |
72
77
 
73
78
  **Functions**
74
79
 
@@ -76,10 +81,12 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
76
81
  | ---------------------------- | :-------: | ----------------------------------------------------------- |
77
82
  | Function declarations | ✅ | Transpiled to Go functions |
78
83
  | Arrow functions | ✅ | Transpiled to anonymous functions |
84
+ | IIFEs | ✅ | `(() => { ... })()` and `(function name() { ... })()` |
79
85
  | Closures over mutable state | ✅ | Functions capturing and mutating outer variables |
80
86
  | Function types | ✅ | `() => number`, `(x: number) => string` as type annotations |
81
87
  | Generics (functions/classes) | ✅ | Type parameters via Go generics |
82
88
  | Default parameter values | ✅ | `function(x = defaultValue)` |
89
+ | Rest parameters | ✅ | `function(...args: T[])` → Go variadic |
83
90
 
84
91
  **Classes & Interfaces**
85
92
 
@@ -87,6 +94,8 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
87
94
  | ------------------- | :-------: | -------------------------------------------------------------- |
88
95
  | Classes | ✅ | Transpiled to Go structs with constructor and receiver methods |
89
96
  | Class inheritance | ✅ | `extends` via embedded structs, `super()` supported |
97
+ | Static members | ✅ | `static method()` / `static prop` → package-level declarations |
98
+ | Getters / Setters | ✅ | `get prop()` → `Get_prop()`, `set prop(v)` → `Set_prop(v)` |
90
99
  | Interfaces | ✅ | Transpiled to Go interfaces, supports `extends` |
91
100
  | Optional properties | ✅ | `prop?: Type` in interfaces/types |
92
101
  | Enums | ✅ | `enum` declarations and member access |
@@ -104,9 +113,16 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
104
113
  | Feature | Supported | Notes |
105
114
  | --------------------- | :-------: | ----------------------------------------------------- |
106
115
  | console.log | ✅ | Mapped to `fmt.Println` |
116
+ | console.error | ✅ | Mapped to `fmt.Fprintln(os.Stderr, ...)` |
107
117
  | console.time/timeEnd | ✅ | Performance measurement via `time.Now` / `time.Since` |
108
118
  | assert | ✅ | Transpiled to `panic` on failure |
109
119
  | parseInt / parseFloat | ✅ | Mapped to Go's `strconv` package |
120
+ | JSON.stringify | ✅ | Mapped to `encoding/json` `Marshal` / `MarshalIndent` |
121
+ | JSON.parse | ✅ | Mapped to `encoding/json` `Unmarshal` |
122
+ | Object.keys/values | ✅ | Map key/value iteration helpers |
123
+ | process.argv | ✅ | Mapped to `os.Args` |
124
+ | process.platform | ✅ | Mapped to `runtime.GOOS` |
125
+ | process.exit | ✅ | Mapped to `os.Exit` |
110
126
 
111
127
  **Math Methods**
112
128
 
@@ -116,6 +132,9 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
116
132
  | Math.floor / ceil / round | ✅ | Mapped to `math.Floor`, `math.Ceil`, `math.Round` |
117
133
  | Math.abs / sqrt / pow | ✅ | Mapped to corresponding `math` functions |
118
134
  | Math.min / max | ✅ | Mapped to `math.Min`, `math.Max` |
135
+ | Math.log / log2 / log10 | ✅ | Mapped to `math.Log`, `math.Log2`, `math.Log10` |
136
+ | Math.sin / cos / tan | ✅ | Mapped to `math.Sin`, `math.Cos`, `math.Tan` |
137
+ | Math.trunc / sign | ✅ | Mapped to `math.Trunc` and inline sign check |
119
138
 
120
139
  **String Methods**
121
140
 
@@ -129,6 +148,9 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
129
148
  | replace / replaceAll | ✅ | Via `strings` package |
130
149
  | charAt / substring / slice | ✅ | Direct Go string indexing/slicing |
131
150
  | concat / repeat | ✅ | String concatenation and `strings.Repeat` |
151
+ | padStart / padEnd | ✅ | Via `strings.Repeat` |
152
+ | match / matchAll / search | ✅ | Via `regexp` package |
153
+ | at | ✅ | Supports negative indices |
132
154
 
133
155
  **Number / Object Methods**
134
156
 
@@ -147,12 +169,15 @@ TypeNative currently supports a focused subset of TypeScript syntax elements tha
147
169
 
148
170
  **Modules & Imports**
149
171
 
150
- | Feature | Supported | Notes |
151
- | ------------------------ | :-------: | ------------------------------------------------------------ |
152
- | Local file imports | ✅ | `import { x } from './file'` transpiled to Go package import |
153
- | Node.js built-in imports | ✅ | `import { join } from 'node:path'` mapped to Go stdlib |
154
- | Go package imports | ✅ | `import { x } from 'go:pkg'` |
155
- | npm package imports | ✅ | `import { x } from 'pkg'` mapped to Go module imports |
156
- | Named exports | ✅ | `export function` / `export const` declarations |
172
+ | Feature | Supported | Notes |
173
+ | ------------------------ | :-------: | ------------------------------------------------------------------ |
174
+ | Named imports | ✅ | `import { x } from './file'` |
175
+ | Default imports | ✅ | `import x from 'pkg'` namespace stripped in output |
176
+ | Namespace imports | ✅ | `import * as x from 'pkg'` |
177
+ | Local file imports | ✅ | Relative paths transpiled to a separate Go file |
178
+ | Node.js built-in imports | ✅ | `import { join } from 'node:path'` mapped to Go stdlib |
179
+ | Go package imports | ✅ | `import { x } from 'go:pkg'` |
180
+ | npm package imports | ✅ | `import { x } from 'pkg'` mapped to Go module imports |
181
+ | Named exports | ✅ | `export function` / `export const` declarations |
157
182
 
158
183
  TypeNative is currently in early development and new features are being added regularly. The goal for `1.0` release is for TypeNative to transpile itself.
package/bin/transpiler.js CHANGED
@@ -6,7 +6,16 @@ const importedPackages = new Set();
6
6
  let outsideNodes = [];
7
7
  const classNames = new Set();
8
8
  let promiseResolveName = '';
9
- const dangerousNames = new Set(['main']);
9
+ // Go keywords that cannot be used as identifiers
10
+ const dangerousNames = new Set([
11
+ 'main',
12
+ // Go reserved keywords
13
+ 'break', 'case', 'chan', 'const', 'continue',
14
+ 'default', 'defer', 'else', 'fallthrough', 'for',
15
+ 'func', 'go', 'goto', 'if', 'import',
16
+ 'interface', 'map', 'package', 'range', 'return',
17
+ 'select', 'struct', 'switch', 'type', 'var',
18
+ ]);
10
19
  const renamedFunctions = new Map();
11
20
  const variableTypes = new Map();
12
21
  const variableGoTypes = new Map();
@@ -19,6 +28,10 @@ const enumNames = new Set();
19
28
  const enumBaseTypes = new Map();
20
29
  // Maps local TS name → Go qualified name (e.g. 'Println' → 'fmt.Println', 'myFmt' → 'fmt')
21
30
  const importAliases = new Map();
31
+ // Tracks static methods per class: Set of "ClassName.methodName" strings
32
+ const classStaticMethods = new Set();
33
+ // Tracks static properties per class: Set of "ClassName.propName" strings
34
+ const classStaticProps = new Set();
22
35
  // Callback for resolving import specifiers to source code.
23
36
  // specifier: the raw import string (relative path or package name)
24
37
  // fromDir: directory of the file containing the import (null = main file's dir)
@@ -30,6 +43,9 @@ let currentFileDir = null;
30
43
  const includedLocalImports = new Set();
31
44
  // Collects Go source files generated from local TS imports (filename → content)
32
45
  let localImportFiles = new Map();
46
+ // Default import namespaces from npm/local packages (e.g. `import ts from 'typescript'` → 'ts')
47
+ // Property accesses on these are stripped: ts.createSourceFile → createSourceFile
48
+ const defaultImportNamespaces = new Set();
33
49
  export function transpileToNative(code, options) {
34
50
  fileResolver = options?.readFile ?? null;
35
51
  currentFileDir = null;
@@ -52,6 +68,9 @@ export function transpileToNative(code, options) {
52
68
  importAliases.clear();
53
69
  includedLocalImports.clear();
54
70
  localImportFiles = new Map();
71
+ defaultImportNamespaces.clear();
72
+ classStaticMethods.clear();
73
+ classStaticProps.clear();
55
74
  const transpiledCode = visit(sourceFile, { addFunctionOutside: true });
56
75
  const transpiledCodeOutside = outsideNodes.map((n) => visit(n, { isOutside: true })).join('\n');
57
76
  const main = `package main
@@ -117,6 +136,10 @@ export function visit(node, options = {}) {
117
136
  }
118
137
  else if (ts.isArrayLiteralExpression(node)) {
119
138
  const type = ts.isVariableDeclaration(node.parent) ? getType(node.parent.type, true) : '';
139
+ const hasSpread = node.elements.some((e) => ts.isSpreadElement(e));
140
+ if (hasSpread) {
141
+ return visitSpreadArrayLiteral(node, type);
142
+ }
120
143
  return `[]${type} {${node.elements.map((e) => visit(e)).join(', ')}}`;
121
144
  }
122
145
  else if (ts.isBlock(node)) {
@@ -137,12 +160,57 @@ export function visit(node, options = {}) {
137
160
  if (ts.isIdentifier(node.expression) && enumNames.has(node.expression.text)) {
138
161
  return `${getSafeName(node.expression.text)}_${getEnumMemberName(node.name)}`;
139
162
  }
163
+ // Strip default import namespace: `ts.createSourceFile` → `createSourceFile`
164
+ if (ts.isIdentifier(node.expression) && defaultImportNamespaces.has(node.expression.text)) {
165
+ return visit(node.name);
166
+ }
167
+ // Static member access: `Counter.count` → `Counter_count`
168
+ if (ts.isIdentifier(node.expression)) {
169
+ const key = `${node.expression.text}.${node.name.text}`;
170
+ if (classStaticMethods.has(key) || classStaticProps.has(key)) {
171
+ return `${node.expression.text}_${node.name.text}`;
172
+ }
173
+ }
140
174
  const leftSide = visit(node.expression);
141
175
  const rightSide = visit(node.name);
142
176
  const objectType = resolveExpressionType(node.expression);
143
177
  return getAcessString(leftSide, rightSide, objectType);
144
178
  }
145
179
  else if (ts.isVariableDeclaration(node)) {
180
+ // Object destructuring: const { x, y } = obj
181
+ if (ts.isObjectBindingPattern(node.name) && node.initializer) {
182
+ const initExpr = visit(node.initializer);
183
+ const parts = node.name.elements.map((el) => {
184
+ const localName = visit(el.name);
185
+ const propName = el.propertyName ? visit(el.propertyName) : localName;
186
+ const defaultVal = el.initializer ? visit(el.initializer) : undefined;
187
+ if (defaultVal) {
188
+ return `${localName} := func() interface{} { if ${initExpr}.${propName} == nil { return ${defaultVal} }; return ${initExpr}.${propName} }()`;
189
+ }
190
+ return `${localName} := ${initExpr}.${propName}`;
191
+ });
192
+ return parts.join(';\n\t');
193
+ }
194
+ // Array destructuring: const [a, b] = arr
195
+ if (ts.isArrayBindingPattern(node.name) && node.initializer) {
196
+ const initExpr = visit(node.initializer);
197
+ const tmpVar = getTempName('arr');
198
+ const parts = [`${tmpVar} := ${initExpr}`];
199
+ node.name.elements.forEach((el, idx) => {
200
+ if (ts.isOmittedExpression(el))
201
+ return;
202
+ const bindEl = el;
203
+ const localName = visit(bindEl.name);
204
+ // Variables starting with _ are intentionally unused — use blank identifier
205
+ if (localName === '_' || localName.startsWith('_')) {
206
+ parts.push(`_ = ${tmpVar}[${idx}]`);
207
+ }
208
+ else {
209
+ parts.push(`${localName} := ${tmpVar}[${idx}]`);
210
+ }
211
+ });
212
+ return parts.join(';\n\t');
213
+ }
146
214
  const type = getType(node.type);
147
215
  // Track variable type for type-aware method dispatch
148
216
  if (ts.isIdentifier(node.name)) {
@@ -197,6 +265,19 @@ export function visit(node, options = {}) {
197
265
  (ts.isPropertyAccessExpression(node.expression) && hasQuestionDot(node.expression))) {
198
266
  return visitOptionalCall(node);
199
267
  }
268
+ // IIFE with named function expression: (function name() { ... })()
269
+ if (ts.isParenthesizedExpression(node.expression) &&
270
+ ts.isFunctionExpression(node.expression.expression)) {
271
+ const fn = node.expression.expression;
272
+ const parameterInfo = getFunctionParametersInfo(fn.parameters);
273
+ if (fn.body && ts.isBlock(fn.body)) {
274
+ prescanVariableDeclarations(fn.body);
275
+ }
276
+ const inferredRetType = inferFunctionBodyReturnType(fn);
277
+ const returnType = inferredRetType ? ` ${inferredRetType}` : '';
278
+ const args = node.arguments.map((a) => visit(a)).join(', ');
279
+ return `func(${parameterInfo.signature})${returnType} ${visit(fn.body, { prefixBlockContent: parameterInfo.prefixBlockContent })}(${args})`;
280
+ }
200
281
  // Handle setTimeout specially to get raw delay value
201
282
  if (ts.isIdentifier(node.expression) && node.expression.text === 'setTimeout') {
202
283
  importedPackages.add('time');
@@ -212,7 +293,11 @@ export function visit(node, options = {}) {
212
293
  const caller = visit(node.expression);
213
294
  const safeCaller = getSafeName(caller);
214
295
  const typeArgs = getTypeArguments(node.typeArguments);
215
- const args = node.arguments.map((a) => visit(a));
296
+ // Handle spread arguments: fn(...arr) fn(arr...)
297
+ const hasSpreadArg = node.arguments.some((a) => ts.isSpreadElement(a));
298
+ const args = hasSpreadArg
299
+ ? node.arguments.map((a) => ts.isSpreadElement(a) ? `${visit(a.expression)}...` : visit(a))
300
+ : node.arguments.map((a) => visit(a));
216
301
  // Resolve object type for type-aware method dispatch
217
302
  let objectType;
218
303
  if (ts.isPropertyAccessExpression(node.expression)) {
@@ -258,9 +343,25 @@ export function visit(node, options = {}) {
258
343
  inline: true
259
344
  })}; ${visit(node.incrementor, { inline: true })}${visit(node.statement)}`;
260
345
  }
346
+ else if (ts.isForInStatement(node)) {
347
+ const varName = ts.isVariableDeclarationList(node.initializer)
348
+ ? visit(node.initializer.declarations[0].name)
349
+ : visit(node.initializer);
350
+ return `for ${varName} := range ${visit(node.expression, { inline: true })}${visit(node.statement)}`;
351
+ }
261
352
  else if (ts.isForOfStatement(node)) {
262
- const iterExpr = visit(node.expression, { inline: true });
263
- const iterType = inferExpressionType(node.expression);
353
+ // Unwrap Object.entries(x) treat x as the iterable
354
+ let iterNode = node.expression;
355
+ if (ts.isCallExpression(iterNode) &&
356
+ ts.isPropertyAccessExpression(iterNode.expression) &&
357
+ ts.isIdentifier(iterNode.expression.expression) &&
358
+ iterNode.expression.expression.text === 'Object' &&
359
+ iterNode.expression.name.text === 'entries' &&
360
+ iterNode.arguments.length > 0) {
361
+ iterNode = iterNode.arguments[0];
362
+ }
363
+ const iterExpr = visit(iterNode, { inline: true });
364
+ const iterType = inferExpressionType(iterNode);
264
365
  if (iterType && iterType.startsWith('map[')) {
265
366
  const valueType = extractMapValueType(iterType);
266
367
  const isSet = valueType === 'struct{}';
@@ -458,11 +559,23 @@ export function visit(node, options = {}) {
458
559
  const properties = new Map();
459
560
  const methods = new Map();
460
561
  for (const member of node.members) {
562
+ const memberModifiers = member.modifiers;
563
+ const isStatic = memberModifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
461
564
  if (ts.isPropertyDeclaration(member) && ts.isIdentifier(member.name)) {
462
- properties.set(member.name.text, getOptionalNodeType(member.type, !!member.questionToken));
565
+ if (isStatic) {
566
+ classStaticProps.add(`${className}.${member.name.text}`);
567
+ }
568
+ else {
569
+ properties.set(member.name.text, getOptionalNodeType(member.type, !!member.questionToken));
570
+ }
463
571
  }
464
572
  if (ts.isMethodDeclaration(member) && ts.isIdentifier(member.name)) {
465
- methods.set(member.name.text, member.type ? getType(member.type) : 'interface{}');
573
+ if (isStatic) {
574
+ classStaticMethods.add(`${className}.${member.name.text}`);
575
+ }
576
+ else {
577
+ methods.set(member.name.text, member.type ? getType(member.type) : 'interface{}');
578
+ }
466
579
  }
467
580
  }
468
581
  classPropertyTypes.set(className, properties);
@@ -520,9 +633,36 @@ export function visit(node, options = {}) {
520
633
  const methodName = visit(member.name);
521
634
  const methodParameterInfo = getFunctionParametersInfo(member.parameters);
522
635
  const returnType = member.type ? ` ${getType(member.type)}` : '';
523
- result += `func (self *${name}${typeParamNames}) ${methodName}(${methodParameterInfo.signature})${returnType} ${visit(member.body, {
524
- prefixBlockContent: methodParameterInfo.prefixBlockContent
525
- })}\n\n`;
636
+ const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
637
+ if (isStatic) {
638
+ // Static methods become package-level functions named ClassName_methodName
639
+ result += `func ${name}_${methodName}(${methodParameterInfo.signature})${returnType} ${visit(member.body, { prefixBlockContent: methodParameterInfo.prefixBlockContent })}\n\n`;
640
+ }
641
+ else {
642
+ result += `func (self *${name}${typeParamNames}) ${methodName}(${methodParameterInfo.signature})${returnType} ${visit(member.body, { prefixBlockContent: methodParameterInfo.prefixBlockContent })}\n\n`;
643
+ }
644
+ }
645
+ else if (ts.isGetAccessor(member)) {
646
+ // Getter: get prop() { ... } → func (self *T) Prop() RetType { ... }
647
+ const getterName = visit(member.name);
648
+ const returnType = member.type ? ` ${getType(member.type)}` : ' interface{}';
649
+ result += `func (self *${name}${typeParamNames}) Get_${getterName}()${returnType} ${visit(member.body)}\n\n`;
650
+ }
651
+ else if (ts.isSetAccessor(member)) {
652
+ // Setter: set prop(val) { ... } → func (self *T) SetProp(val ValType) { ... }
653
+ const setterName = visit(member.name);
654
+ const parameterInfo = getFunctionParametersInfo(member.parameters);
655
+ result += `func (self *${name}${typeParamNames}) Set_${setterName}(${parameterInfo.signature}) ${visit(member.body, { prefixBlockContent: parameterInfo.prefixBlockContent })}\n\n`;
656
+ }
657
+ }
658
+ // Static property declarations → package-level vars named ClassName_propName
659
+ for (const member of node.members) {
660
+ if (ts.isPropertyDeclaration(member) &&
661
+ member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
662
+ const fieldName = visit(member.name);
663
+ const fieldType = getOptionalNodeType(member.type, !!member.questionToken);
664
+ const initializer = member.initializer ? ` = ${visit(member.initializer)}` : '';
665
+ result += `var ${name}_${fieldName} ${fieldType}${initializer}\n\n`;
526
666
  }
527
667
  }
528
668
  return result.trim();
@@ -565,6 +705,12 @@ export function visit(node, options = {}) {
565
705
  if (ts.isPropertyAssignment(p)) {
566
706
  return `${visit(p.name)}: ${visit(p.initializer)}`;
567
707
  }
708
+ // Shorthand: { name } → name: name
709
+ if (ts.isShorthandPropertyAssignment(p)) {
710
+ const name = visit(p.name);
711
+ return `${name}: ${name}`;
712
+ }
713
+ // Spread: { ...obj } — not easily supported in Go structs, omit
568
714
  return '';
569
715
  })
570
716
  .filter((p) => p)
@@ -585,7 +731,8 @@ export function visit(node, options = {}) {
585
731
  }
586
732
  const syntaxKind = ts.SyntaxKind[node.kind];
587
733
  if (!['FirstStatement', 'EndOfFileToken'].includes(syntaxKind)) {
588
- console.log(ts.SyntaxKind[node.kind], node.getText());
734
+ const snippet = node.getText().substring(0, 60).replace(/\n/g, ' ');
735
+ console.warn(`[TypeNative] Unsupported syntax: ${syntaxKind} — "${snippet}"`);
589
736
  }
590
737
  ts.forEachChild(node, (subNode) => {
591
738
  code += visit(subNode);
@@ -603,6 +750,34 @@ function getTypeText(typeNode) {
603
750
  function toGoStringLiteral(value) {
604
751
  return JSON.stringify(value);
605
752
  }
753
+ function visitSpreadArrayLiteral(node, elemType) {
754
+ const chunks = [];
755
+ for (const el of node.elements) {
756
+ if (ts.isSpreadElement(el)) {
757
+ chunks.push({ isSpread: true, items: [el.expression] });
758
+ }
759
+ else {
760
+ const last = chunks[chunks.length - 1];
761
+ if (last && !last.isSpread) {
762
+ last.items.push(el);
763
+ }
764
+ else {
765
+ chunks.push({ isSpread: false, items: [el] });
766
+ }
767
+ }
768
+ }
769
+ const baseType = elemType || 'interface{}';
770
+ let result = `[]${baseType}{}`;
771
+ for (const chunk of chunks) {
772
+ if (chunk.isSpread) {
773
+ result = `append(${result}, ${visit(chunk.items[0])}...)`;
774
+ }
775
+ else {
776
+ result = `append(${result}, ${chunk.items.map((e) => visit(e)).join(', ')})`;
777
+ }
778
+ }
779
+ return result;
780
+ }
606
781
  function visitTemplateExpression(node) {
607
782
  const parts = [];
608
783
  if (node.head.text.length > 0) {
@@ -963,8 +1138,8 @@ function buildArrayCallbackInfo(callback, elementType, forcedReturnType) {
963
1138
  params.push(`${visit(callback.parameters[2].name)} []${elementType}`);
964
1139
  }
965
1140
  const body = ts.isBlock(callback.body)
966
- ? visit(callback.body)
967
- : `{\n\t\treturn ${visit(callback.body)};\n\t}`;
1141
+ ? visit(callback.body, { inline: true })
1142
+ : `{ return ${visit(callback.body)}; }`;
968
1143
  return {
969
1144
  fnExpr: `func(${params.join(', ')}) ${callbackReturnType} ${body}`,
970
1145
  paramCount,
@@ -987,11 +1162,24 @@ function buildArrayCallbackInvocation(callbackInfo, itemVar, indexVar, arrayVar)
987
1162
  args.push(arrayVar);
988
1163
  return `(${callbackInfo.fnExpr})(${args.join(', ')})`;
989
1164
  }
1165
+ // Like buildArrayCallbackInvocation but for reduce: (acc, item, idx, arr)
1166
+ function buildArrayCallbackInvocationReduce(callbackInfo, accVar, itemVar, indexVar, arrayVar) {
1167
+ const args = [];
1168
+ if (callbackInfo.paramCount > 0)
1169
+ args.push(accVar);
1170
+ if (callbackInfo.paramCount > 1)
1171
+ args.push(itemVar);
1172
+ if (callbackInfo.paramCount > 2)
1173
+ args.push(`float64(${indexVar})`);
1174
+ if (callbackInfo.paramCount > 3)
1175
+ args.push(arrayVar);
1176
+ return `(${callbackInfo.fnExpr})(${args.join(', ')})`;
1177
+ }
990
1178
  function visitArrayHigherOrderCall(node) {
991
1179
  if (!ts.isPropertyAccessExpression(node.expression))
992
1180
  return undefined;
993
1181
  const methodName = node.expression.name.text;
994
- if (!['map', 'filter', 'some', 'find', 'join'].includes(methodName)) {
1182
+ if (!['map', 'filter', 'some', 'find', 'findIndex', 'every', 'forEach', 'reduce', 'join'].includes(methodName)) {
995
1183
  return undefined;
996
1184
  }
997
1185
  const arrayExprNode = node.expression.expression;
@@ -1039,6 +1227,43 @@ function visitArrayHigherOrderCall(node) {
1039
1227
  const callbackCall = buildArrayCallbackInvocation(callbackInfo, itemVar, idxVar, arrVar);
1040
1228
  return `func() bool { ${arrVar} := ${arrayExpr}; for ${rangeIndexVar}, ${itemVar} := range ${arrVar} { if ${callbackCall} { return true } }; return false }()`;
1041
1229
  }
1230
+ if (methodName === 'findIndex') {
1231
+ const callbackInfo = buildArrayCallbackInfo(callback, elementType, 'bool');
1232
+ const callbackCall = buildArrayCallbackInvocation(callbackInfo, itemVar, idxVar, arrVar);
1233
+ return `func() float64 { ${arrVar} := ${arrayExpr}; for ${idxVar}, ${itemVar} := range ${arrVar} { if ${callbackCall} { return float64(${idxVar}) } }; return float64(-1) }()`;
1234
+ }
1235
+ if (methodName === 'every') {
1236
+ const callbackInfo = buildArrayCallbackInfo(callback, elementType, 'bool');
1237
+ const rangeIndexVar = callbackInfo.paramCount > 1 ? idxVar : '_';
1238
+ const callbackCall = buildArrayCallbackInvocation(callbackInfo, itemVar, idxVar, arrVar);
1239
+ return `func() bool { ${arrVar} := ${arrayExpr}; for ${rangeIndexVar}, ${itemVar} := range ${arrVar} { if !(${callbackCall}) { return false } }; return true }()`;
1240
+ }
1241
+ if (methodName === 'forEach') {
1242
+ const callbackInfo = buildArrayCallbackInfo(callback, elementType, '');
1243
+ const rangeIndexVar = callbackInfo.paramCount > 1 ? idxVar : '_';
1244
+ const callbackCall = buildArrayCallbackInvocation(callbackInfo, itemVar, idxVar, arrVar);
1245
+ return `func() { ${arrVar} := ${arrayExpr}; for ${rangeIndexVar}, ${itemVar} := range ${arrVar} { ${callbackCall} } }()`;
1246
+ }
1247
+ if (methodName === 'reduce') {
1248
+ const reduceCallback = node.arguments[0];
1249
+ if (!reduceCallback)
1250
+ return undefined;
1251
+ const initialValue = node.arguments[1] ? visit(node.arguments[1]) : undefined;
1252
+ const accType = initialValue
1253
+ ? (inferExpressionType(node.arguments[1]) ?? elementType)
1254
+ : elementType;
1255
+ const accVar = getTempName('acc');
1256
+ // Build a callback that takes (acc, item, idx, arr) — param count determines what gets passed
1257
+ const cbInfo = buildArrayCallbackInfo(reduceCallback, elementType, accType ?? 'interface{}');
1258
+ const cbCall = buildArrayCallbackInvocationReduce(cbInfo, accVar, itemVar, idxVar, arrVar);
1259
+ // Only include the index loop var if the callback uses it (paramCount > 2)
1260
+ const reduceIdxVar = cbInfo.paramCount > 2 ? idxVar : '_';
1261
+ if (initialValue !== undefined) {
1262
+ return `func() ${accType} { ${arrVar} := ${arrayExpr}; ${accVar} := ${initialValue}; for ${reduceIdxVar}, ${itemVar} := range ${arrVar} { ${accVar} = ${cbCall} }; return ${accVar} }()`;
1263
+ }
1264
+ return `func() ${elementType} { ${arrVar} := ${arrayExpr}; ${accVar} := ${arrVar}[0]; for ${reduceIdxVar}, ${itemVar} := range ${arrVar}[1:] { ${accVar} = ${cbCall} }; return ${accVar} }()`;
1265
+ }
1266
+ // find
1042
1267
  const callbackInfo = buildArrayCallbackInfo(callback, elementType, 'bool');
1043
1268
  const rangeIndexVar = callbackInfo.paramCount > 1 ? idxVar : '_';
1044
1269
  const callbackCall = buildArrayCallbackInvocation(callbackInfo, itemVar, idxVar, arrVar);
@@ -1292,6 +1517,21 @@ function getAcessString(leftSide, rightSide, objectType) {
1292
1517
  if (rightSide === 'size' && (objectType === 'Map' || objectType === 'Set')) {
1293
1518
  return `float64(len(${leftSide}))`;
1294
1519
  }
1520
+ // process global properties
1521
+ if (leftSide === 'process') {
1522
+ if (rightSide === 'argv') {
1523
+ importedPackages.add('os');
1524
+ return 'os.Args';
1525
+ }
1526
+ if (rightSide === 'platform') {
1527
+ importedPackages.add('runtime');
1528
+ return 'runtime.GOOS';
1529
+ }
1530
+ if (rightSide === 'env') {
1531
+ // process.env.X is handled by nested property access; just return a placeholder object
1532
+ return 'os.Environ()';
1533
+ }
1534
+ }
1295
1535
  return `${leftSide}.${rightSide}`;
1296
1536
  }
1297
1537
  const callHandlers = {
@@ -1355,7 +1595,84 @@ const callHandlers = {
1355
1595
  parseFloat: (_caller, args) => {
1356
1596
  importedPackages.add('strconv');
1357
1597
  return `func() float64 { v, _ := strconv.ParseFloat(${args[0]}, 64); return v }()`;
1358
- }
1598
+ },
1599
+ 'process.exit': (_caller, args) => {
1600
+ importedPackages.add('os');
1601
+ return `os.Exit(int(${args[0] ?? '0'}))`;
1602
+ },
1603
+ 'process.cwd': () => {
1604
+ importedPackages.add('os');
1605
+ return `func() string { __d, _ := os.Getwd(); return __d }()`;
1606
+ },
1607
+ 'JSON.stringify': (_caller, args) => {
1608
+ importedPackages.add('encoding/json');
1609
+ if (args.length >= 3) {
1610
+ return `func() string { __b, _ := json.MarshalIndent(${args[0]}, "", " "); return string(__b) }()`;
1611
+ }
1612
+ return `func() string { __b, _ := json.Marshal(${args[0]}); return string(__b) }()`;
1613
+ },
1614
+ 'JSON.parse': (_caller, args) => {
1615
+ importedPackages.add('encoding/json');
1616
+ return `func() interface{} { var __v interface{}; json.Unmarshal([]byte(${args[0]}), &__v); return __v }()`;
1617
+ },
1618
+ 'Object.keys': (_caller, args) => {
1619
+ importedPackages.add('maps');
1620
+ return `func() []string { __k := make([]string, 0); for k := range ${args[0]} { __k = append(__k, k) }; return __k }()`;
1621
+ },
1622
+ 'Object.values': (_caller, args) => {
1623
+ return `func() []interface{} { __v := make([]interface{}, 0); for _, v := range ${args[0]} { __v = append(__v, v) }; return __v }()`;
1624
+ },
1625
+ 'Object.entries': (_caller, args) => {
1626
+ // When used outside for...of, produce a slice of [key, value] pairs — rarely needed
1627
+ return args[0];
1628
+ },
1629
+ 'Math.log': (_caller, args) => {
1630
+ importedPackages.add('math');
1631
+ return `math.Log(${args[0]})`;
1632
+ },
1633
+ 'Math.log2': (_caller, args) => {
1634
+ importedPackages.add('math');
1635
+ return `math.Log2(${args[0]})`;
1636
+ },
1637
+ 'Math.log10': (_caller, args) => {
1638
+ importedPackages.add('math');
1639
+ return `math.Log10(${args[0]})`;
1640
+ },
1641
+ 'Math.sin': (_caller, args) => {
1642
+ importedPackages.add('math');
1643
+ return `math.Sin(${args[0]})`;
1644
+ },
1645
+ 'Math.cos': (_caller, args) => {
1646
+ importedPackages.add('math');
1647
+ return `math.Cos(${args[0]})`;
1648
+ },
1649
+ 'Math.tan': (_caller, args) => {
1650
+ importedPackages.add('math');
1651
+ return `math.Tan(${args[0]})`;
1652
+ },
1653
+ 'Math.trunc': (_caller, args) => {
1654
+ importedPackages.add('math');
1655
+ return `math.Trunc(${args[0]})`;
1656
+ },
1657
+ 'Math.sign': (_caller, args) => {
1658
+ return `func() float64 { if ${args[0]} > 0 { return 1 }; if ${args[0]} < 0 { return -1 }; return 0 }()`;
1659
+ },
1660
+ 'console.error': (_caller, args) => {
1661
+ importedPackages.add('fmt');
1662
+ importedPackages.add('os');
1663
+ return `fmt.Fprintln(os.Stderr, ${args.join(', ')})`;
1664
+ },
1665
+ 'String': (_caller, args) => {
1666
+ importedPackages.add('fmt');
1667
+ return `fmt.Sprintf("%v", ${args[0]})`;
1668
+ },
1669
+ 'Number': (_caller, args) => {
1670
+ importedPackages.add('strconv');
1671
+ return `func() float64 { v, _ := strconv.ParseFloat(fmt.Sprintf("%v", ${args[0]}), 64); return v }()`;
1672
+ },
1673
+ 'Boolean': (_caller, args) => {
1674
+ return `(${args[0]} != nil && ${args[0]} != false && ${args[0]} != 0 && ${args[0]} != "")`;
1675
+ },
1359
1676
  };
1360
1677
  const stringMethodHandlers = {
1361
1678
  split: (obj, args) => {
@@ -1422,6 +1739,32 @@ const stringMethodHandlers = {
1422
1739
  return `${obj}[int(${args[0]}):]`;
1423
1740
  },
1424
1741
  concat: (obj, args) => `${obj} + ${args.join(' + ')}`,
1742
+ padStart: (obj, args) => {
1743
+ importedPackages.add('fmt');
1744
+ importedPackages.add('strings');
1745
+ const pad = args[1] ?? '" "';
1746
+ return `func() string { __s := ${obj}; __n := int(${args[0]}) - len(__s); if __n > 0 { __s = strings.Repeat(${pad}, __n)[:__n] + __s }; return __s }()`;
1747
+ },
1748
+ padEnd: (obj, args) => {
1749
+ importedPackages.add('strings');
1750
+ const pad = args[1] ?? '" "';
1751
+ return `func() string { __s := ${obj}; __n := int(${args[0]}) - len(__s); if __n > 0 { __s = __s + strings.Repeat(${pad}, __n)[:__n] }; return __s }()`;
1752
+ },
1753
+ match: (obj, args) => {
1754
+ importedPackages.add('regexp');
1755
+ return `regexp.MustCompile(${args[0]}).FindStringSubmatch(${obj})`;
1756
+ },
1757
+ matchAll: (obj, args) => {
1758
+ importedPackages.add('regexp');
1759
+ return `regexp.MustCompile(${args[0]}).FindAllStringSubmatch(${obj}, -1)`;
1760
+ },
1761
+ search: (obj, args) => {
1762
+ importedPackages.add('regexp');
1763
+ return `float64(regexp.MustCompile(${args[0]}).FindStringIndex(${obj})[0])`;
1764
+ },
1765
+ at: (obj, args) => {
1766
+ return `func() string { __i := int(${args[0]}); if __i < 0 { __i = len(${obj}) + __i }; return string(${obj}[__i]) }()`;
1767
+ },
1425
1768
  toString: (obj) => {
1426
1769
  importedPackages.add('fmt');
1427
1770
  return `fmt.Sprintf("%v", ${obj})`;
@@ -1433,6 +1776,13 @@ const regexpMethodHandlers = {
1433
1776
  };
1434
1777
  const arrayMethodHandlers = {
1435
1778
  push: (obj, args) => `${obj} = append(${obj}, ${args.join(', ')})`,
1779
+ pop: (obj) => {
1780
+ return `func() interface{} { if len(${obj}) == 0 { return nil }; __last := ${obj}[len(${obj})-1]; ${obj} = ${obj}[:len(${obj})-1]; return __last }()`;
1781
+ },
1782
+ shift: (obj) => {
1783
+ return `func() interface{} { if len(${obj}) == 0 { return nil }; __first := ${obj}[0]; ${obj} = ${obj}[1:]; return __first }()`;
1784
+ },
1785
+ unshift: (obj, args) => `${obj} = append([]interface{}{${args.join(', ')}}, ${obj}...)`,
1436
1786
  join: (obj, args) => {
1437
1787
  importedPackages.add('strings');
1438
1788
  return `strings.Join(${obj}, ${args[0] ?? '""'})`;
@@ -1442,10 +1792,30 @@ const arrayMethodHandlers = {
1442
1792
  return `${obj}[int(${args[0]}):int(${args[1]})]`;
1443
1793
  return `${obj}[int(${args[0]}):]`;
1444
1794
  },
1795
+ reverse: (obj) => {
1796
+ importedPackages.add('slices');
1797
+ return `func() interface{} { slices.Reverse(${obj}); return nil }()`;
1798
+ },
1799
+ sort: (obj) => {
1800
+ importedPackages.add('sort');
1801
+ return `func() interface{} { sort.Slice(${obj}, func(i, j int) bool { return fmt.Sprintf("%v", ${obj}[i]) < fmt.Sprintf("%v", ${obj}[j]) }); return nil }()`;
1802
+ },
1803
+ indexOf: (obj, args) => {
1804
+ return `func() float64 { for __i, __v := range ${obj} { if fmt.Sprintf("%v", __v) == fmt.Sprintf("%v", ${args[0]}) { return float64(__i) } }; return float64(-1) }()`;
1805
+ },
1806
+ includes: (obj, args) => {
1807
+ return `func() bool { for _, __v := range ${obj} { if fmt.Sprintf("%v", __v) == fmt.Sprintf("%v", ${args[0]}) { return true } }; return false }()`;
1808
+ },
1809
+ concat: (obj, args) => `append(${obj}, ${args.join(', ')}...)`,
1810
+ flat: (obj) => obj,
1445
1811
  toString: (obj) => {
1446
1812
  importedPackages.add('fmt');
1447
1813
  return `fmt.Sprintf("%v", ${obj})`;
1448
- }
1814
+ },
1815
+ // padStart / padEnd for string arrays (rarely used, but added for completeness)
1816
+ at: (obj, args) => {
1817
+ return `func() interface{} { __i := int(${args[0]}); if __i < 0 { __i = len(${obj}) + __i }; if __i < 0 || __i >= len(${obj}) { return nil }; return ${obj}[__i] }()`;
1818
+ },
1449
1819
  };
1450
1820
  const mapMethodHandlers = {
1451
1821
  set: (obj, args) => `${obj}[${args[0]}] = ${args[1]}`,
@@ -1578,6 +1948,17 @@ function getTypeArguments(typeArguments) {
1578
1948
  return `[${args.join(', ')}]`;
1579
1949
  }
1580
1950
  function getParameterGoType(param) {
1951
+ // Rest parameter: ...args — use variadic syntax
1952
+ if (param.dotDotDotToken) {
1953
+ if (param.type) {
1954
+ let baseType = getType(param.type);
1955
+ // If annotated as T[], the variadic type is T
1956
+ if (baseType.startsWith('[]'))
1957
+ baseType = baseType.slice(2);
1958
+ return `...${baseType}`;
1959
+ }
1960
+ return '...interface{}';
1961
+ }
1581
1962
  if (param.type) {
1582
1963
  const explicitType = getType(param.type);
1583
1964
  return explicitType === ':' ? 'interface{}' : explicitType;
@@ -1952,6 +2333,17 @@ function visitImportDeclaration(node) {
1952
2333
  includeLocalImport(resolved.content, resolved.dir, goFileName);
1953
2334
  }
1954
2335
  }
2336
+ // Register default/namespace import name as a "stripped" namespace
2337
+ // e.g. `import ts from 'typescript'` → ts.createSourceFile → createSourceFile
2338
+ if (node.importClause) {
2339
+ const clause = node.importClause;
2340
+ if (clause.name) {
2341
+ defaultImportNamespaces.add(clause.name.text);
2342
+ }
2343
+ else if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {
2344
+ defaultImportNamespaces.add(clause.namedBindings.name.text);
2345
+ }
2346
+ }
1955
2347
  return '';
1956
2348
  }
1957
2349
  function getForOfVarNames(initializer) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typenative",
3
- "version": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "description": "Build native applications using Typescript.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -40,7 +40,10 @@
40
40
  "test25": "node ./bin/index --source test/Test25.spec.ts --script",
41
41
  "test25_export": "node ./bin/index --source test/Test25-export.spec.ts --script",
42
42
  "test26": "node ./bin/index --source test/Test26.spec.ts --script",
43
- "test27": "node ./bin/index --source test/Test27.spec.ts --script"
43
+ "test27": "node ./bin/index --source test/Test27.spec.ts --script",
44
+ "test28": "node ./bin/index --source test/test28.spec.ts --script",
45
+ "test29": "node ./bin/index --source test/test29.spec.ts --script",
46
+ "test30": "node ./bin/index --source test/test30.spec.ts --script"
44
47
  },
45
48
  "repository": {
46
49
  "type": "git",
@@ -99,6 +99,26 @@ interface Array<T> extends IterableIterator<T> {
99
99
  * Returns the value of the first element in the array where callback is true, and undefined otherwise.
100
100
  */
101
101
  find(callback: (value: T, index?: number, array?: T[]) => boolean): T | undefined;
102
+ /**
103
+ * Returns the index of the first element that satisfies the callback, or -1.
104
+ */
105
+ findIndex(callback: (value: T, index?: number, array?: T[]) => boolean): number;
106
+ /**
107
+ * Determines whether all elements satisfy the callback.
108
+ */
109
+ every(callback: (value: T, index?: number, array?: T[]) => boolean): boolean;
110
+ /**
111
+ * Performs the callback for each element.
112
+ */
113
+ forEach(callback: (value: T, index?: number, array?: T[]) => void): void;
114
+ /**
115
+ * Calls the callback function on each element of the array, accumulating a result.
116
+ */
117
+ reduce<U>(
118
+ callback: (accumulator: U, value: T, index?: number, array?: T[]) => U,
119
+ initialValue: U
120
+ ): U;
121
+ reduce(callback: (accumulator: T, value: T, index?: number, array?: T[]) => T): T;
102
122
  /**
103
123
  * Returns the index of the first occurrence of a value in an array, or -1 if it is not present.
104
124
  */
@@ -107,6 +127,38 @@ interface Array<T> extends IterableIterator<T> {
107
127
  * Determines whether an array includes a certain element.
108
128
  */
109
129
  includes(searchElement: T): boolean;
130
+ /**
131
+ * Removes the last element from an array and returns it.
132
+ */
133
+ pop(): T | undefined;
134
+ /**
135
+ * Removes the first element from an array and returns it.
136
+ */
137
+ shift(): T | undefined;
138
+ /**
139
+ * Inserts elements at the beginning of an array.
140
+ */
141
+ unshift(...items: T[]): number;
142
+ /**
143
+ * Reverses the elements of an array in place.
144
+ */
145
+ reverse(): T[];
146
+ /**
147
+ * Sorts the elements of an array in place.
148
+ */
149
+ sort(compareFn?: (a: T, b: T) => number): T[];
150
+ /**
151
+ * Returns a new array formed by applying callback to each element and then flattening.
152
+ */
153
+ flat(): T[];
154
+ /**
155
+ * Merges two or more arrays.
156
+ */
157
+ concat(...items: T[]): T[];
158
+ /**
159
+ * Returns the element at the given index (supports negative indices).
160
+ */
161
+ at(index: number): T | undefined;
110
162
  /**
111
163
  * Returns a string representation of an array.
112
164
  */
@@ -152,6 +204,18 @@ interface String {
152
204
  repeat(count: number): string;
153
205
  /** Concatenates strings. */
154
206
  concat(...strings: string[]): string;
207
+ /** Pads the start of a string with another string to a total length. */
208
+ padStart(targetLength: number, padString?: string): string;
209
+ /** Pads the end of a string with another string to a total length. */
210
+ padEnd(targetLength: number, padString?: string): string;
211
+ /** Matches a string against a regex and returns the matches. */
212
+ match(regexp: string | RegExp): string[] | null;
213
+ /** Matches all occurrences of a regex. */
214
+ matchAll(regexp: string | RegExp): string[][];
215
+ /** Searches for a match and returns the index. */
216
+ search(regexp: string | RegExp): number;
217
+ /** Returns the element at the given index (supports negative indices). */
218
+ at(index: number): string | undefined;
155
219
  /** Returns a string representation. */
156
220
  toString(): string;
157
221
  [index: number]: string;
@@ -159,6 +223,7 @@ interface String {
159
223
 
160
224
  interface Console {
161
225
  log(...data: any[]): void;
226
+ error(...data: any[]): void;
162
227
  time(label?: string): void;
163
228
  timeEnd(label?: string): void;
164
229
  }
@@ -174,11 +239,44 @@ interface Math {
174
239
  min(a: number, b: number): number;
175
240
  sqrt(x: number): number;
176
241
  pow(base: number, exponent: number): number;
242
+ log(x: number): number;
243
+ log2(x: number): number;
244
+ log10(x: number): number;
245
+ sin(x: number): number;
246
+ cos(x: number): number;
247
+ tan(x: number): number;
248
+ trunc(x: number): number;
249
+ sign(x: number): number;
177
250
  }
178
251
  declare var Math: Math;
179
252
 
180
- declare function parseInt(s: string): number;
253
+ declare function parseInt(s: string, radix?: number): number;
181
254
  declare function parseFloat(s: string): number;
255
+ declare function String(value: any): string;
256
+ declare function Number(value: any): number;
257
+ declare function Boolean(value: any): boolean;
258
+
259
+ interface JSON {
260
+ stringify(value: any, replacer?: any, space?: number | string): string;
261
+ parse(text: string): any;
262
+ }
263
+ declare var JSON: JSON;
264
+
265
+ interface ObjectConstructor {
266
+ keys(obj: any): string[];
267
+ values(obj: any): any[];
268
+ entries(obj: any): [string, any][];
269
+ }
270
+ declare var Object: ObjectConstructor;
271
+
272
+ interface Process {
273
+ argv: string[];
274
+ platform: string;
275
+ exit(code?: number): never;
276
+ cwd(): string;
277
+ env: { [key: string]: string | undefined };
278
+ }
279
+ declare var process: Process;
182
280
 
183
281
  interface Promise<T> {
184
282
  then(callback: (value: T) => void): void;
package/TODO.md DELETED
@@ -1,29 +0,0 @@
1
- **index.ts needs:**
2
-
3
- | Feature | Example |
4
- | ------------------------------- | ------------------------------------------------------------------- |
5
- | Default imports | `import inquirer from 'inquirer'`, `import fs from 'fs-extra'` |
6
- | `process` global | `process.argv`, `process.platform` |
7
- | Array `findIndex` | `process.argv.findIndex(a => a === '--script')` |
8
- | `JSON.parse` / `JSON.stringify` | `JSON.parse(fs.readFileSync(...))`, `JSON.stringify(pckg, null, 2)` |
9
- | Named async IIFE | `(async function main() { ... })()` |
10
-
11
- **transpiler.ts additionally needs:**
12
-
13
- | Feature | Example |
14
- | ----------------------------------- | --------------------------------------------------- |
15
- | Default imports | `import ts from 'typescript'` |
16
- | Spread in array literals | `[...importedPackages]`, `[...arr1, ...arr2]` |
17
- | `for...of` with tuple destructuring | `for (const [funcName, fn] of Object.entries(...))` |
18
- | `Object.entries()` | `Object.entries(mapping.functions)` |
19
- | Arrow function IIFE | `(() => { ... })()` |
20
- | Array `findIndex` | `parameters.findIndex(p => !!p.initializer)` |
21
-
22
- **Priority order** (most blocking first):
23
-
24
- 1. **Default imports** — used at the top of both files, nothing runs without this
25
- 2. **Spread in array literals** — used throughout transpiler.ts for array construction
26
- 3. **`for...of` with tuple destructuring + `Object.entries`** — used for iterating import mappings
27
- 4. **`process` global** — core to CLI argument parsing in index.ts
28
- 5. **IIFE** — the entire entry point of index.ts is an async IIFE
29
- 6. **`findIndex`**, **`JSON.parse/stringify`** — utility methods used in both files