TypeScript in this repo
SkillWeb & browsingLets your agent write TypeScript that passes the repo's lint and type rules and convert .js files to .ts safely.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the TypeScript in this repo skill
About this capability
Write TypeScript that satisfies this repo's lint and tsconfig rules, and convert an existing .js file to .ts without breaking its call sites. Use when adding or editing a .ts file, converting a .js file, adding the first .ts browser spec, or hitting a type-check or ESLint failure.
What this skill tells your AI
The instructions your AI receives, as published by liberatedpixelcup/universal-lpc-spritesheet-character-generator in .agents/skills/typescript/SKILL.md and read by ahel’s review.
New code is .ts, including tests, scripts, and Vite plugins. Do not add new
.js. testem.cjs is the only CommonJS file.
npm run type-check (tsc --noEmit) and npm run lint both gate PRs via the
Lint workflow. Run npm run type-check and npm run lint:fix after any edit
under sources/, scripts/, vite/, or tests/ — all four are in
tsconfig.json include. tsc is the typescript package, which this repo
aliases to @typescript/typescript6. @typescript/native is also in
devDependencies and is unused by workflows.
Erasable syntax only
Node runs first-party .ts by type-stripping it, with no tsx and no compile
step. erasableSyntaxOnly is on, so no enums, no namespaces, no parameter
properties. Anything that would need to emit runtime code is a type error.
Relative imports use the extension of the file on disk, so a .ts file
importing a still-.js module writes .js:
import { markNonExecutableLinesInLcov } from "./mark-non-executable-lines.js";
allowImportingTsExtensions is on, so importing ./foo.ts is correct once the
target is converted. Getting this backwards is the most common failure when
converting a file — every importer has to move with it.
tsconfig deliberately relaxes three strictest flags
tsconfig.json extends @tsconfig/strictest and then
turns off noUncheckedIndexedAccess, exactOptionalPropertyTypes, and
noPropertyAccessFromIndexSignature, each with a comment explaining why. Do not
re-enable them as a drive-by; pixel-index loops and metadata config bags depend
on them being off.
Lint rules that bite
- Unused bindings that must exist need a
_prefix.argsIgnorePattern,varsIgnorePattern, andcaughtErrorsIgnorePatternare all^_. console.*is an error exceptconsole.error. Useconsole.error, ordebugLog/debugWarn/debugGroup/debugGroupEnd/debugTablefromsources/utils/debug.ts, which are gated on localhost or?debug=.eslint.config.jsappliestypescript-eslint's recommended preset to**/*.tsonly, and layers per-directory blocks forsources/,scripts/+vite/,tests/,tests/node/, andtests/visual/. A converted file moves from the.jsblock to the.tsblock and can pick up rules it was never subject to, so lint the file after renaming, not before.
Converting a .js file
Four non-test .js files remain:
scripts/coverage/mark-non-executable-lines.jsvite/vite-plugin-coverage-collect.jseslint.config.jsplaywright.config.js
The rest are under tests/. Ordinary *_spec.js files are not named by
hardcoded path. These harness files are:
tests/tests.js— named intests_run.htmltests/bdd-globals.js— themocha-globalsalias target invite.config.ts, in two HTML import maps (scripts/zip/zip-export-profile-runner.html,tests/fixtures/issue-382/issue382-golden-runner.html), and asserted by path intests/node/scripts/generateSources/vite_config_factory_and_resolve_spec.tstests/node/run-node-tests.js— named intestem.cjsbefore_teststests/vitest-setup.js— imported bytests/tests.jstests/testem-firefox-user.js— named intestem.cjs
Before renaming anything, grep for the filename. Breaking a harness path fails a command rather than the type-check:
scripts/coverage/mark-non-executable-lines.js— named inpackage.jsontest:node:coverage, and imported bymerge-browser-coverage.ts.vite/vite-plugin-coverage-collect.js— imported byvite.config.ts.
Checklist for a conversion:
git mvthe file, then update every importer to the new extension.- Update hardcoded paths in
package.json,testem.cjs, HTML files, and any spec that asserts on the path. npm run type-check— the file is newly checked, so expect real errors.npm run lint:fix— it may have moved into a stricter ESLint block.- Run whatever command names the file, not just the test suite. A broken
before_testspath or import map does not surface as a test failure. - Check
codecov.ymlignore:. If the file is not ignored, it now owes covered lines: coverage.
Adding a .ts browser spec
Canvas already has several TypeScript specs (renderer_spec.ts,
renderer-composite_spec.ts, load-images_spec.ts, and the
palette-recolor-*_spec.ts files). Leftover *_spec.js files under
tests/ stay JS until converted. Two things differ from
those leftover .js specs:
-
Register it with its real extension, since relative imports use the on-disk extension:
import "./canvas/renderer-composite_spec.ts"; -
It is type-checked under
@tsconfig/strictestas soon as it exists, which leftover.jsspecs are not (checkJsis off). Runnpm run type-check; annotate DOM hosts, sinon sandboxes, and catalog handles the wayrenderer-composite_spec.tsalready does.
Everything else about writing the spec is unchanged: write-spec.
Signals
- GitHub stars
- 2k
- Forks
- 580
- Last commit
- Sep 2026
- Hacker News mentions
- 20
Advanced
- Catalog kind
- skill
- Gateway key
typescript-liberatedpixelcup- Source
- github.com/liberatedpixelcup/universal-lpc-spritesheet-character-generator