AgentStack
SKILL verified MIT Self-run

Js To Typescript

skill-siddharth00-agent-revamp-skills-js-to-typescript · by Siddharth00

Converts one JavaScript source file to strict TypeScript 5.x, resolves all tsc errors without @ts-ignore, and confirms the Jest suite is unchanged.

No reviews yet
0 installs
4 views
0.0% view→install

Install

$ agentstack add skill-siddharth00-agent-revamp-skills-js-to-typescript

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Js To Typescript? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

1. Purpose

This skill converts a single JavaScript source file (ES2020+) to strict-mode TypeScript 5.x as one atomic step in an incremental file-by-file migration. It is run by a frontend or full-stack engineer once per file, in isolation from all other files — never applied to the whole repo in a single pass. The coexistence strategy relies on allowJs: true in tsconfig, which lets unconverted .js files continue compiling alongside newly converted .ts files throughout the transition. The primary risks are implicit any widening — where removing a JSDoc annotation or leaving an untyped parameter silently degrades type safety across callers — and engineers suppressing tsc errors with @ts-ignore to meet a deadline, which converts a type error into permanent type debt. Both are treated as hard failures by this skill.


2. Trigger Conditions

Use when:

  • target_file is a .js source file under src/ (not a test file, not a config file).
  • tsconfig.json in repo_root already has "allowJs": true and "strict": true — Phase 3 preparation is complete.
  • ts-jest (or equivalent) is configured so Jest runs .ts and .js files without a config change between them.
  • npx jest exits 0 on the current commit — the suite is green before you start.
  • The file appears in the migration manifest produced by /revamp-spec.
  • All TypeScript files already in src/ compile cleanly (npx tsc --noEmit exits 0 before this run).

Do NOT use when:

  • target_file is a test file (*.test.js, *.spec.js, __tests__/*.js) — test files must be converted only after every source file they import has been converted.
  • target_file has more than 300 lines and zero test coverage — flag for manual review before converting; the equivalence tests cannot catch regressions in untested code.
  • npx tsc --noEmit currently reports errors on any .ts file in the repo — do not add new .ts files on top of existing unresolved errors.
  • Phase 3 preparation (tsconfig setup, ts-jest config, allowJs: true) is not yet complete — run skills/03-prepare/ first.
  • You are considering converting more than one file in this skill invocation — run the skill once per file; parallelism here creates merge conflicts and tangled error attribution.

3. Inputs

Required:

| Input | Type | Description | |-------|------|-------------| | target_file | file-path | Repo-root-relative path to the .js file to convert. Example: src/utils/parseDate.js. Must exist and be a source file, not a test. | | repo_root | file-path | Absolute path to the repository root. Used as the working directory for all tsc and jest invocations. |

Optional:

| Input | Type | Default | Description | |-------|------|---------|-------------| | max_tsc_errors | integer | 20 | If tsc --noEmit reports more errors than this threshold after renaming the file, revert and flag for manual review. Raise for large, complex files; lower for small utility files. | | jest_pattern | string | Basename of target_file without extension | Passed to jest --testPathPattern. Override when the test file's name doesn't match the source file's basename. Example: parseDate resolves to tests named parseDate.test.js. | | dry_run | boolean | false | When true: read and analyze the file, write the any-map and symbol inventory, but do not rename or modify any source file. Useful for previewing the annotation burden before committing to conversion. |


4. Steps

  1. Read /tsconfig.json. Confirm both "allowJs": true and "strict": true are present in the compiler options.
  • If either is missing: STOP. Do not proceed. Ask: "tsconfig.json is missing `. This skill requires both allowJs: true and strict: true to be set before conversion. Should I add them, or should we run skills/03-prepare/` first?"
  1. Run npx jest --passWithNoTests --testPathPattern= --no-coverage from `. Record the full output and exit code as **prejestresult`**.
  • If exit code is non-zero: STOP. The test suite is already failing before conversion. Report the failing tests and do not touch target_file. The engineer must fix the suite first.
  1. Run npx tsc --noEmit from `. Record the full output and error count as **pretscresult`**.
  • If any error in pre_tsc_result references target_file: STOP. Ask: "tsc already reports errors in `` before conversion. Address these first, or exclude this file from the current run."
  • Record the total pre-conversion error count for comparison in Step 8.
  1. Read target_file. Scan every function parameter, variable declaration, and function return position that lacks an explicit type annotation and would become implicit any under strict: true. Write each occurrence to output/js-to-typescript-any-map-.json with this shape per entry: { "line": , "identifier": "", "kind": "param|var|return", "context": "" }.
  1. → Hand off to code-archaeologist (see Section 5. Agent Handoffs). Wait for output/js-to-typescript-inventory-.md to be written before continuing.
  1. Read output/js-to-typescript-inventory-.md. For each exported symbol listed:

a. Derive the narrowest accurate TypeScript type based on call-site evidence in the inventory. Acceptable types: specific primitives, interfaces, union types, generics. Not acceptable: any, object, Function, {}. b. If a type cannot be determined from usage evidence alone, use unknown and insert a line comment // TODO(ts-migration): narrow — . This is the only acceptable placeholder; never use @ts-ignore. c. Record the chosen type for each exported symbol in the migration log.

  1. If dry_run is true: write the migration log with the proposed annotations and STOP. Do not rename or modify the source file.
  1. Rename ` from .js to .ts (e.g., src/utils/parseDate.jssrc/utils/parseDate.ts`). Apply all type annotations derived in Step 6. Write the annotated file.
  • If the rename or write fails: restore from git (git checkout -- ), write the failure reason to the migration log, STOP.
  1. Run npx tsc --noEmit from ``. Count errors. Record full output in the migration log.
  • If error count > max_tsc_errors: revert the rename (git mv src/.../parseDate.ts src/.../parseDate.js && git checkout -- src/.../parseDate.js), write a revert entry to the migration log, and STOP with: "Reverted `` — tsc errors exceeded threshold of . File flagged for manual review in migration log."
  • If error count is 0–max_tsc_errors: categorize each error as one of: implicit-any | missing-property | incompatible-return | type-assertion-needed | other. Log the category and line for each.
  1. Address each tsc error from Step 9, one at a time, in order of category: implicit-any first, then missing-property, then incompatible-return, then the rest. For each error:

a. Read the error message and the surrounding code context (±5 lines). b. Apply the narrowest correct type fix. Do not use @ts-ignore. Do not use as any. c. After fixing, re-run npx tsc --noEmit --noEmit and confirm the specific error is gone before moving to the next.

  • If an individual error persists after three distinct fix attempts: leave a // TODO(ts-migration): unresolved — comment at the offending line, log the error as needs-manual-review in the migration log, and continue to the next error. Do not block on it.
  1. Run npx tsc --noEmit from `` one final time. Confirm exit code is 0 and error count referencing the converted file is 0. Log result.
  • If errors remain: for any error without a // TODO(ts-migration): comment, return to Step 10. If all remaining errors have TODO comments, proceed — the manual-review flags are intentional and logged.
  1. Grep for @ts-ignore in the converted .ts file: grep -n '@ts-ignore' /.ts.
  • If any match is found: this is a hard failure. Remove each @ts-ignore, resolve the underlying error properly (return to Step 10 logic), or escalate to manual review with a TODO comment. Do not proceed to Step 13 until the file is @ts-ignore-free.
  1. Run npx jest --passWithNoTests --testPathPattern= --no-coverage from `. Record full output and exit code as **postjestresult`**.
  • If exit code is non-zero: revert the .ts file (git checkout -- /.ts; then git mv back to .js), write failure details to the migration log, STOP with: "Jest suite failed after conversion — reverted. See migration log for failing test names."
  1. Write all outputs declared in Section 7. Run every Equivalence Test in Section 6 and record each result (pass/fail + evidence) in output/js-to-typescript-equiv-.md. Evaluate every item in Section 9 Done Criteria; report pass/fail inline, then print the final verdict.

5. Agent Handoffs

code-archaeologist

  • File: agents/code-archaeologist.md
  • Triggered by: Step 5
  • Prompt template:

``` TASK: Inventory all exported symbols in and trace their import sites across the repository. For each exported symbol, report:

  • name and kind (function | class | const | type alias)
  • parameter names and any type information inferable from JSDoc, usage patterns,

or argument shapes at call sites

  • return type if inferable from return statements or call-site assignments
  • file path and line number of every import site in SCOPE

Flag any symbol imported but never called (dead export). Flag any symbol where callers pass heterogeneous argument types (type is ambiguous). REPOROOT: SCOPE: /src OUTPUTFILE: output/js-to-typescript-inventory-.md FORMAT: markdown ```


6. Equivalence Tests

| Test Name | Input | Expected Output | Tool | |-----------|-------|-----------------|------| | jest-pre | npx jest --passWithNoTests --testPathPattern= --no-coverage run against the original .js file (Step 2 result) | Exit code 0. Record test count (passed/failed/skipped) as the baseline for jest-post. | Bash — result already captured in Step 2 as pre_jest_result. | | jest-post | npx jest --passWithNoTests --testPathPattern= --no-coverage run against the converted .ts file (Step 13 result) | Exit code 0. Passed/failed/skipped counts are identical to jest-pre baseline. Any count divergence is a fail, even if exit code is 0. | Bash — result already captured in Step 13 as post_jest_result. | | tsc-clean | npx tsc --noEmit from ` after all Step 10–11 fixes | Exit code 0; 0 errors in output. A non-zero exit or any error line referencing .ts is a fail. | Bash — result already captured in Step 11. | | no-ts-ignore | grep -n '@ts-ignore' /.ts | No output — grep exits 1 (no matches). Any match is a hard fail. | Bash | | no-implicit-any | npx tsc --noEmit --noImplicitAny from , output filtered to lines referencing .ts | 0 error lines referencing .ts. | Bash | | exports-unchanged | Read the symbol inventory from output/js-to-typescript-inventory-.md; grep /.ts for each exported name | Every name exported from the original .js is exported from the .ts file. No export is removed or renamed. Narrowed types are acceptable; widened types (e.g., a previously-typed return becoming any or unknown`) are a fail. | Bash + Read |


7. Outputs

| Artifact | Path Pattern | Format | Description | |----------|-------------|--------|-------------| | Implicit-any map | output/js-to-typescript-any-map-.json | json | Pre-conversion list of every position that would become implicit any under strict mode, with line number, identifier, and kind. Consumed in Step 6 to guide annotation; retained as evidence that all implicit-any positions were addressed. | | Symbol inventory | output/js-to-typescript-inventory-.md | markdown | Produced by code-archaeologist in Step 5. Lists every exported symbol, its call sites, and inferred types. Consumed in Step 6 and by the PR reviewer to verify no exports were silently altered. | | Migration log | output/js-to-typescript-log-.md | markdown | Chronological record of every tsc error encountered (category, line, resolution), any manual-review flags, the final tsc error count before and after, and the assumptions list and confidence level. Consumed by /validate and by the engineer reviewing the PR. | | Equivalence test results | output/js-to-typescript-equiv-.md | markdown | Pass/fail verdict for every row in Section 6, with the raw command output or evidence attached. Required by Section 9 Done Criteria. |


8. References

  • references/migration-anti-patterns.md — "Confidence Without Evidence" (§7) applies to every type annotation in Step 6; "Skipping Equivalence Validation" (§3) is why jest-post is a hard gate.
  • references/stack-compatibility-matrix.md — "Runtime / Language Compatibility: Node.js 16→20" row; ESM/CJS interop notes apply if the repo mixes module systems.
  • skills/03-prepare/ — tsconfig scaffolding, ts-jest configuration, and allowJs: true setup must be complete before this skill runs.
  • skills/05-validate/ — run /validate after all .js files in a module or feature boundary are converted to confirm end-to-end behavioral equivalence at the module level.
  • agents/code-archaeologist.md — the agent invoked in Step 5; review its output format before debugging unexpected inventory results.
  • https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html — official incremental migration guide; the allowJs + strict coexistence approach this skill uses is documented there with additional rationale.

9. Done Criteria

  • [ ] target_file no longer exists as a .js file — ls /.js exits with "No such file or directory" (or equivalent). If dry_run was true, this gate does not apply; skip and note.
  • [ ] The converted .ts file exists at /.ts — file read succeeds and returns the annotated content from Step 8.
  • [ ] npx tsc --noEmit exits 0 with 0 errors referencing .ts — confirmed by Step 11 output in the migration log.
  • [ ] No @ts-ignore in .tsgrep -n '@ts-ignore' /.ts returns no output (no-ts-ignore equivalence test is pass).
  • [ ] No as any cast introduced in .ts that was not present in the original .jsgrep -n ' as any' /.ts output compared against pre-conversion any-map; any new occurrence is a fail.
  • [ ] jest-post equivalence test recorded as pass in output/js-to-typescript-equiv-.md — test counts match jest-pre baseline exactly.
  • [ ] tsc-clean equivalence test recorded as pass — exit code 0, 0 error lines.
  • [ ] no-ts-ignore equivalence test recorded as pass — grep returned no matches.
  • [ ] no-implicit-any equivalence test recorded as pass — 0 errors referencing .ts.
  • [ ] exports-unchanged equivalence test recorded as pass — every exported name from the .js inventory is present and exported in the .ts file.
  • [ ] All output files listed in Section 7 exist at their declared paths — verify each with a file read.
  • [ ] Every equivalence test in Section 6 has a recorded result in output/js-to-typescript-equiv-.md — no test name is missing from the results file.
  • [ ] No equivalence test in Section 6 is recorded as fail — grep the results file for fail; zero matches required.
  • [ ] The migration log includes a confidence level (High / Medium / Low) — grep output/js-to-typescript-log-.md for Confidence:.
  • [ ] The migration log includes a numbered assumptions list — grep output/js-to-typescript-log-.md for Assumptions:.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.