forcedotcom/sf-skills

experience-lwc-typescript-migrate

Use when converting an existing JavaScript Lightning Web Component (.js, .html, .css) to TypeScript with full type annotations and a matching .d.ts file that exposes only the component's @api surface.

Voir la source
Document Skill original

Rendu depuis le dépôt source en conservant titres, exemples, code, tableaux, liens et images.

<!-- adk-managed-skill -->

Converting LWC to TypeScript

Convert a Lightning Web Component bundle from JavaScript to TypeScript. The deliverable is a fully-typed .ts implementation plus a .d.ts file that only exposes @api members (the public surface other LWCs consume).

When to Use This Skill

  • User wants to migrate a single component or a folder of components from

.js to .ts.

  • User needs a .d.ts for an existing LWC so other components (or an

external TypeScript host) can import it safely.

  • User is adding type annotations to an already-renamed .ts LWC that

hasn't been properly typed yet.

  • User wants JSDoc-style type hints upgraded to real TypeScript types.

Prerequisites

  • The component builds and runs correctly in JavaScript today.
  • git is available (the rename must preserve history via git mv).
  • A TypeScript compiler is wired into the build (either the SFDX TS

pipeline or a standalone tsc step).


Workflow

Step 1 — Read the component

Open every file in the bundle:

text
componentName/
├── componentName.js
├── componentName.html
├── componentName.css
└── (possibly) __tests__/, __utam__/, existing .d.ts

Understand:

  • What extends LightningElement? What is the class name?
  • Which fields and methods carry the @api decorator?
  • Which properties/methods have existing JSDoc (use as a type hint

starting point, but validate against actual usage — JSDoc lies).

  • Which parameters / return types can you infer from how the code is

called internally?

Step 2 — Rename .js.ts using git mv

bash
git mv componentName/componentName.js componentName/componentName.ts

Repeat for any helper .js files in the bundle (unless they're already .ts). Never plain mv — that loses the history link TypeScript reviewers rely on.

Step 3 — Add type annotations in the .ts

Apply types in this priority order so you stop as soon as the public contract is solid:

  1. `@api` properties and methods first. Generate JSDoc if it's

missing, then translate JSDoc types to TS syntax (string, number, boolean, Promise<T>). Validate each JSDoc claim against the code before trusting it.

  1. Complex shapes become `interface` or `type` aliases — not inline

shapes repeated everywhere.

  1. Optional members use `?` only when the value is genuinely allowed

to be undefined. Do not sprinkle ? defensively.

  1. Private/internal state — still type it, but don't export the

types. Use private for members that must never be touched by consumers.

  1. Event handlers — prefer precise DOM event types:
  • MouseEvent for onclick (and other click-like handlers). click

is dispatched as a MouseEvent — including keyboard-activated clicks — so typing it as PointerEvent would let handlers rely on pointer-only fields (pointerType, pressure, etc.) that are undefined in those cases.

  • PointerEvent for onpointerdown / onpointerup / onpointermove

and other pointer* handlers where pointer-specific fields are actually meaningful.

  • CustomEvent<{ detail: ... }> for LWC custom events.
  • Event is the last resort; document why when using it.
  1. Async methods always return Promise<T> — never bare T.
  2. Avoid `any`. If you genuinely can't type something, use unknown

and narrow with a type guard.

Reference patterns

Load [[assets/type-patterns.ts|assets/type-patterns.ts]] as an inline example covering property types, method types, and event handler types.

Step 4 — Generate the .d.ts

Create componentName.d.ts next to the .ts. It must:

  • Contain only `@api` members — no private state, no internal

methods, no lifecycle hooks unless they are themselves @api.

  • Preserve @api JSDoc verbatim (including @type, @required,

@default, @param, @returns tags) directly above each declaration.

  • Declare the LWC module namespace c/componentName (or the org's

namespace if different).

Template: load [[assets/dts-template.ts|assets/dts-template.ts]] as the starting .d.ts shape.

If the component has no @api members, still produce the module declaration with a comment explaining there's no public surface — don't skip the file.

Step 5 — Compile and test

  • Run the TypeScript compiler (tsc --noEmit or the build's equivalent).

Resolve every error before calling it done; no @ts-ignore patches.

  • Run the component's existing Jest tests. The behavior should be

identical.

  • Run the bundled consumer-finder unconditionally — empty output is a

valid result, not a reason to skip. The script resolves the search paths from sfdx-project.json's packageDirectories (or falls back to <project-root>), rejects any entry that escapes the project root, and performs the LWC-import search internally so the invocation is fully deterministic:

bash
"<skill_dir>/scripts/find-consumers.sh" "<project-root>" "<componentName>"

For each match, confirm the consumer's expected types still align with the new .d.ts public surface.

Step 6 — Expected final bundle shape

text
componentName/
├── componentName.ts          # Main TypeScript implementation
├── componentName.html        # Template (unchanged)
├── componentName.css         # Styles (unchanged)
└── componentName.d.ts        # Type definitions (new)

Verification Checklist

Before conversion:

  • [ ] Component is valid JS and all tests pass.
  • [ ] You've identified every @api member and its intended type.

After conversion:

  • [ ] git mv was used so history is preserved.
  • [ ] Every variable and parameter in the .ts has a concrete type

(no implicit any).

  • [ ] Complex object shapes live in interface / type aliases, not

inline repeats.

  • [ ] Optional ? is only on genuinely optional fields.
  • [ ] .d.ts exists, declares c/componentName, extends

LightningElement, includes only @api members.

  • [ ] Every @api JSDoc is preserved verbatim in the .d.ts.
  • [ ] tsc passes with zero errors; no @ts-ignore or any used as a

workaround.

  • [ ] Jest tests still pass.

Common Pitfalls

  • Using `any` to silence errors. Solve the actual type instead.

If the value is truly unknown, use unknown + a type guard.

  • Including private members in the `.d.ts`. The .d.ts is the

public contract. Internal lifecycle and helpers must not leak.

  • Losing JSDoc during the rename. Scan before and after — JSDoc

comments on @api members must appear in both the .ts and .d.ts.

  • Skipping `git mv`. Makes review miserable and confuses blame.
  • Forgetting async return types. foo() with an async keyword

always returns a Promise. Declare it.

  • Typing `onclick` as `PointerEvent`. click is a MouseEvent

(keyboard-triggered clicks included), so PointerEvent fields like pointerType are undefined for those events. Type onclick as MouseEvent; reserve PointerEvent for onpointer* handlers. Use MouseEvent | TouchEvent only when the code branches on TouchEvent distinctly.

Support Resources

du même dépôt

Autres Skills

Tous les Skills
forcedotcom
Communauté

agentforce-d360-analyze

Data Cloud 360° view of a single Agentforce session. TRIGGER when user asks to trace, inspect, summarize, or describe a specific Agentforce session by session id (Agent Session UUID 019d… or MessagingSession id 0Mw…). Also triggers on session discovery — find/list/search sessions by time, agent, channel, outcome, or conversation text — when the user has no session id yet. DO NOT TRIGGER for design-time architecture questions (use agentforce-architecture-analyze instead) or for runtime perf/latency/SLO questions that require platform telemetry beyond Data Cloud.

installations
1
GitHub Stars
972
Mis à jour
7 sept.
forcedotcom
Communauté

agentforce-generate

Build, modify, audit, repair, optimize, debug, and deploy agents with Agentforce Agent Script. TRIGGER when: user creates, reviews, or changes .agent files or aiAuthoringBundle metadata; asks to fix AgentScript, audit an existing agent, run an AgentScript health check, common-pitfall review, or baseline-versus-candidate repair loop; changes a response, action, subagent, route, state flow, or Agent Spec; previews, debugs, deploys, publishes, or tests agents; uses sf agent generate/preview/publish/test; or manages Agentforce MCP servers, tools, assets, or authentication. DO NOT TRIGGER when: Apex, Flow, Prompt Template, Experience Cloud, or general Salesforce CLI work is unrelated to Agent Script; or the primary input is a production session or trace ID rather than an agent artifact.

installations
1
GitHub Stars
972
Mis à jour
7 sept.
forcedotcom
Communauté

platform-quick-deploy

Deploy validated metadata to a Production Salesforce org without re-running tests. TRIGGER when the user wants to deploy to production, says 'quick deploy', 'promote', 'ship to prod', or has just validated and wants to push the change live. REQUIRES a recent sf project deploy validate job ID (≤10 days old, ≤3 days for --use-most-recent). DO NOT TRIGGER for sandbox/scratch deploys (use platform-metadata-deploy) or unvalidated deploys (use platform-deploy-validate first).

installations
1
GitHub Stars
972
Mis à jour
7 sept.
forcedotcom
Communauté

agentforce-test

Write, run, and analyze structured test suites for Agentforce agents — functional AND security. TRIGGER when: user writes or modifies test spec YAML (AiEvaluationDefinition); runs sf agent test create, run, run-eval, or results commands; asks about test coverage strategy, metric selection, or custom evaluations; interprets test results or diagnoses test failures; asks about batch testing, regression suites, or CI/CD test integration; requests security testing, OWASP LLM Top 10, red-teaming, penetration testing, prompt-injection tests, a security grade, or a vulnerability assessment of an agent. DO NOT TRIGGER when: user creates, modifies, previews, or debugs .agent files (use agentforce-generate); deploys or publishes agents; writes Agent Script code; uses sf agent preview for development iteration; analyzes production session traces (use agentforce-observe); performs a static safety review of .agent file content (use agentforce-generate Section 15).

installations
3
GitHub Stars
972
Mis à jour
7 sept.