Install
$ agentstack add skill-siddharth00-agent-revamp-skills-js-to-typescript ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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.
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_fileis a.jssource file undersrc/(not a test file, not a config file).tsconfig.jsoninrepo_rootalready has"allowJs": trueand"strict": true— Phase 3 preparation is complete.ts-jest(or equivalent) is configured so Jest runs.tsand.jsfiles without a config change between them.npx jestexits 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 --noEmitexits 0 before this run).
Do NOT use when:
target_fileis 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_filehas 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 --noEmitcurrently reports errors on any.tsfile in the repo — do not add new.tsfiles on top of existing unresolved errors.- Phase 3 preparation (
tsconfigsetup,ts-jestconfig,allowJs: true) is not yet complete — runskills/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
- Read
/tsconfig.json. Confirm both"allowJs": trueand"strict": trueare present in the compiler options.
- If either is missing: STOP. Do not proceed. Ask: "tsconfig.json is missing `
. This skill requires bothallowJs: trueandstrict: trueto be set before conversion. Should I add them, or should we runskills/03-prepare/` first?"
- Run
npx jest --passWithNoTests --testPathPattern= --no-coveragefrom `. 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.
- Run
npx tsc --noEmitfrom `. Record the full output and error count as **pretscresult`**.
- If any error in
pre_tsc_resultreferencestarget_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.
- Read
target_file. Scan every function parameter, variable declaration, and function return position that lacks an explicit type annotation and would becomeimplicit anyunderstrict: true. Write each occurrence tooutput/js-to-typescript-any-map-.jsonwith this shape per entry:{ "line": , "identifier": "", "kind": "param|var|return", "context": "" }.
- → Hand off to
code-archaeologist(see Section 5. Agent Handoffs). Wait foroutput/js-to-typescript-inventory-.mdto be written before continuing.
- 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.
- If
dry_runistrue: write the migration log with the proposed annotations and STOP. Do not rename or modify the source file.
- Rename `
from.jsto.ts(e.g.,src/utils/parseDate.js→src/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.
- Run
npx tsc --noEmitfrom ``. 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.
- Address each tsc error from Step 9, one at a time, in order of category:
implicit-anyfirst, thenmissing-property, thenincompatible-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 asneeds-manual-reviewin the migration log, and continue to the next error. Do not block on it.
- Run
npx tsc --noEmitfrom `` 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.
- Grep for
@ts-ignorein the converted.tsfile: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.
- Run
npx jest --passWithNoTests --testPathPattern= --no-coveragefrom `. Record full output and exit code as **postjestresult`**.
- If exit code is non-zero: revert the
.tsfile (git checkout -- /.ts; thengit mvback to.js), write failure details to the migration log, STOP with: "Jest suite failed after conversion — reverted. See migration log for failing test names."
- 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 whyjest-postis 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, andallowJs: truesetup must be complete before this skill runs.skills/05-validate/— run/validateafter all.jsfiles 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; theallowJs+strictcoexistence approach this skill uses is documented there with additional rationale.
9. Done Criteria
- [ ]
target_fileno longer exists as a.jsfile —ls /.jsexits with "No such file or directory" (or equivalent). Ifdry_runwastrue, this gate does not apply; skip and note. - [ ] The converted
.tsfile exists at/.ts— file read succeeds and returns the annotated content from Step 8. - [ ]
npx tsc --noEmitexits 0 with 0 errors referencing.ts— confirmed by Step 11 output in the migration log. - [ ] No
@ts-ignorein.ts—grep -n '@ts-ignore' /.tsreturns no output (no-ts-ignoreequivalence test is pass). - [ ] No
as anycast introduced in.tsthat was not present in the original.js—grep -n ' as any' /.tsoutput compared against pre-conversion any-map; any new occurrence is a fail. - [ ]
jest-postequivalence test recorded as pass inoutput/js-to-typescript-equiv-.md— test counts matchjest-prebaseline exactly. - [ ]
tsc-cleanequivalence test recorded as pass — exit code 0, 0 error lines. - [ ]
no-ts-ignoreequivalence test recorded as pass — grep returned no matches. - [ ]
no-implicit-anyequivalence test recorded as pass — 0 errors referencing.ts. - [ ]
exports-unchangedequivalence test recorded as pass — every exported name from the.jsinventory is present and exported in the.tsfile. - [ ] 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-.mdforConfidence:. - [ ] The migration log includes a numbered assumptions list — grep
output/js-to-typescript-log-.mdforAssumptions:.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Siddharth00
- Source: Siddharth00/agent-revamp-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.