javascript-idioms
SkillDev toolsPlain JavaScript (ES2024+) idioms — ESM, CJS interop, runtime patterns without types. Use ONLY when TypeScript is unavailable; for TS load typescript-idioms.
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 javascript-idioms skill
What this skill tells your AI
The instructions your AI receives, as published by irahardianto/awesome-agv in .agents/skills/javascript-idioms/SKILL.md and read by ahel’s review.
JavaScript Idioms and Patterns
Modern JavaScript (ES2024+) rewards modules, async/await, and functional patterns. Idiomatic JS = strict mode, modular, well-tested.
Scope: Plain JavaScript only — projects with no
tsconfig.json. This skill is intentionally thin: most JS guidance (coercion traps, async pitfalls, scope bugs, security, collections, performance) is shared with TypeScript and lives in one place to avoid divergence.Loading guards:
- If
tsconfig.jsonexists, do NOT load this skill — load@.agents/skills/typescript-idioms/SKILL.mdinstead. TypeScript is preferred whenever available.- Coercion / async / scope / security / collection / performance pitfalls: see
@.agents/skills/typescript-idioms/references/ts-patterns-and-anti-patterns.md— despite the filename, it is scoped to "TypeScript/JavaScript" and covers runtime pitfalls that apply to plain JS verbatim.- Project layout: see
@.agents/skills/typescript-idioms/references/project-structure.md(the generic backend/library/monorepo layouts are language-level, not TS-only).
Module System
- ES modules over CommonJS for all new code:
// ✅ ESM import { createTask } from './task-service.js'; export function handler(req, res) { ... } // ❌ CommonJS (legacy only) const { createTask } = require('./task-service'); - Always use
.jsextensions in ESM relative imports — Node.js ESM requires them; bundlers accept them. package.json"type": "module"to enable ESM by default; use.cjsfor any CommonJS holdouts.- CJS/ESM interop —
import default from './cjs.cjs'works; named exports from CJS are not statically analyzable, prefermodule.exports = { named }+const { named } = require(...)or migrate to ESM.
Declarations and Strict Mode
constby default,letwhen reassignment needed, nevervar. (varhoisting/closure bugs: seets-patterns-and-anti-patterns.md§3.)- Enable strict mode —
'use strict';at file top in scripts. Strict mode is implicit in ESM modules ("type": "module"inpackage.json) and class bodies. - Optional chaining and nullish coalescing (prefer
??over||to avoid0/''falsy traps):const title = task?.title ?? 'Untitled'; const count = config?.scoring?.default ?? 0; - Destructuring with defaults for clean parameter handling:
function createTask({ title, priority = 'medium', tags = [] }) { ... }
Runtime Without Types
Since there is no compiler to catch mistakes, lean harder on:
- Runtime validation at boundaries — use Zod (works in plain JS) or
ajvto validate external input. Don't trust unvalidated I/O. - Defensive narrowing —
typeof,Array.isArray(),Object.hasOwn()checks before property access. (Coercion traps: seets-patterns-and-anti-patterns.md§1.) - JSDoc for public APIs —
@param,@returns,@throwsgive editors and tools type hints without a TS toolchain. structuredClone()for deep copies (notJSON.parse(JSON.stringify()))— lossy and throws on cycles).
Error Handling
For universal error handling principles, see
@.agents/rules/error-handling-principles.md. Below: JS-specific only.
- Domain error classes (never throw primitives — loses stack trace):
class DomainError extends Error { constructor(message) { super(message); this.name = this.constructor.name; } } class NotFoundError extends DomainError { constructor(resource, id) { super(`${resource} '${id}' not found`); this.resource = resource; this.resourceId = id; } } - Never
catchwithout handling. Empty catch blocks are forbidden. - Always handle promise rejections — never floating/unhandled (see
ts-patterns-and-anti-patterns.md§2 for the full async pitfall catalog).
Naming
- camelCase for functions, variables. PascalCase for classes.
- UPPER_SNAKE_CASE for constants.
- Prefix booleans:
isActive,hasPermission,canEdit.
Testing
Vitest (preferred — ESM-native, zero-config) or Jest. Testing Library for DOM. (TypeScript skill mandates Vitest; in plain JS either is acceptable but Vitest is recommended.)
Toolchain and Formatting
| Tool | Purpose | Command |
|---|---|---|
| Prettier | Formatting | npx prettier --write . |
| ESLint | Linting | npx eslint . |
npm audit / pnpm audit | CVE scanning | npm audit |
Default package manager:
pnpm(matches the TypeScript skill). Usenpmonly if the project already has apackage-lock.json.
Related
- TypeScript Idioms @.agents/skills/typescript-idioms/SKILL.md (load this instead if tsconfig.json exists)
- TS/JS Patterns & Anti-Patterns @.agents/skills/typescript-idioms/references/ts-patterns-and-anti-patterns.md (shared coercion/async/scope/security pitfalls)
- Code Idioms and Conventions @.agents/rules/code-idioms-and-conventions.md
- Testing Strategy @.agents/rules/testing-strategy.md
- Error Handling Principles @.agents/rules/error-handling-principles.md
Signals
- GitHub stars
- 156
- Forks
- 53
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
javascript-idioms- Source
- github.com/irahardianto/awesome-agv