TypeScript / JavaScript Standards
Standards for TypeScript and JavaScript code.
Package Manager
- Prefer
bun over npm
- Use
bun install instead of npm install
- Use
bun run instead of npm run
- Use
bunx instead of npx
Strict Mode
- Enable
strict: true in tsconfig.json
- No
any escape hatches without justification — if unavoidable, add a comment
explaining why
Type Patterns
Prefer interface for object shapes; use type for unions, intersections, and
mapped types
Use satisfies over as for type narrowing — preserves the inferred type while
validating the shape
Avoid enum — use as const objects instead:
// Good
const Status = {
Active: "active",
Inactive: "inactive",
} as const;
type Status = (typeof Status)[keyof typeof Status];
// Avoid
enum Status {
Active = "active",
Inactive = "inactive",
}
Prefer discriminated unions over optional fields for state modeling
Error Handling
Use unknown in catch clauses, not any:
// Good
catch (err: unknown) {
if (err instanceof SpecificError) { ... }
}
// Bad
catch (err: any) { ... }
Never swallow errors with empty catch blocks
Prefer typed error results (Result<T, E> pattern) over thrown exceptions for
expected failure paths
Imports
- Use type-only imports for types:
import type { Foo } from "./foo";
- Avoid barrel files (
index.ts re-exports) in libraries — they defeat tree-shaking
and obscure dependency graphs
Naming
PascalCase for types, interfaces, classes, and React components
camelCase for variables, functions, and methods
UPPER_SNAKE_CASE for constants and environment variable names
- Prefix boolean variables/props with
is, has, should, can
Formatting Rules
- More than 1 arg/param requires a trailing comma (consistent with the
stand-py skill)
- Be explicit with named arguments in object parameters when more than 1 property
Linting
Follow the lint skill for linting and formatting workflow.
Testing
- Prefer Vitest over Jest
- Use test functions, not test classes
- Leverage
describe blocks for grouping, not class hierarchies
- Use
beforeEach / afterEach for shared setup/teardown
- Use
it.each or test.each for parameterized tests
// Good
describe("parseConfig", () => {
it("returns defaults for empty input", () => {
expect(parseConfig({})).toEqual(defaults);
});
it.each([
{ input: "yes", expected: true },
{ input: "no", expected: false },
])("parses '$input' as $expected", ({ input, expected }) => {
expect(parseBoolean(input)).toBe(expected);
});
});
React
When working in React codebases:
- Function components only — no class components
- Prefer hooks over HOCs and render props
- Named exports for components (no
export default)
- Co-locate component, styles, and tests in the same directory
- Extract custom hooks when logic is reused across components
1---2name: stand-ts3description: TypeScript and JavaScript standards. Use when writing TS/JS code. Covers strict mode, type patterns, error handling, imports, naming, testing, React conventions, and package management with bun.4---56# TypeScript / JavaScript Standards78Standards for TypeScript and JavaScript code.910## Package Manager1112- Prefer `bun` over `npm`13- Use `bun install` instead of `npm install`14- Use `bun run` instead of `npm run`15- Use `bunx` instead of `npx`1617## Strict Mode1819- Enable `strict: true` in `tsconfig.json`20- No `any` escape hatches without justification — if unavoidable, add a comment21 explaining why2223## Type Patterns2425- Prefer `interface` for object shapes; use `type` for unions, intersections, and26 mapped types27- Use `satisfies` over `as` for type narrowing — preserves the inferred type while28 validating the shape29- Avoid `enum` — use `as const` objects instead:3031 ```typescript32 // Good33 const Status = {34 Active: "active",35 Inactive: "inactive",36 } as const;37 type Status = (typeof Status)[keyof typeof Status];3839 // Avoid40 enum Status {41 Active = "active",42 Inactive = "inactive",43 }44 ```4546- Prefer discriminated unions over optional fields for state modeling4748## Error Handling4950- Use `unknown` in catch clauses, not `any`:5152 ```typescript53 // Good54 catch (err: unknown) {55 if (err instanceof SpecificError) { ... }56 }5758 // Bad59 catch (err: any) { ... }60 ```6162- Never swallow errors with empty catch blocks63- Prefer typed error results (`Result<T, E>` pattern) over thrown exceptions for64 expected failure paths6566## Imports6768- Use type-only imports for types: `import type { Foo } from "./foo";`69- Avoid barrel files (`index.ts` re-exports) in libraries — they defeat tree-shaking70 and obscure dependency graphs7172## Naming7374- `PascalCase` for types, interfaces, classes, and React components75- `camelCase` for variables, functions, and methods76- `UPPER_SNAKE_CASE` for constants and environment variable names77- Prefix boolean variables/props with `is`, `has`, `should`, `can`7879## Formatting Rules8081- More than 1 arg/param requires a trailing comma (consistent with the `stand-py` skill)82- Be explicit with named arguments in object parameters when more than 1 property8384## Linting8586Follow the `lint` skill for linting and formatting workflow.8788## Testing8990- Prefer Vitest over Jest91- Use test functions, not test classes92- Leverage `describe` blocks for grouping, not class hierarchies93- Use `beforeEach` / `afterEach` for shared setup/teardown94- Use `it.each` or `test.each` for parameterized tests9596```typescript97// Good98describe("parseConfig", () => {99 it("returns defaults for empty input", () => {100 expect(parseConfig({})).toEqual(defaults);101 });102103 it.each([104 { input: "yes", expected: true },105 { input: "no", expected: false },106 ])("parses '$input' as $expected", ({ input, expected }) => {107 expect(parseBoolean(input)).toBe(expected);108 });109});110```111112## React113114When working in React codebases:115116- Function components only — no class components117- Prefer hooks over HOCs and render props118- Named exports for components (no `export default`)119- Co-locate component, styles, and tests in the same directory120- Extract custom hooks when logic is reused across components