typescript-conventions
TypeScript coding conventions
Apply conventions from the documentation, AGENTS.md files, lint rules, and configuration of the repository containing the active file first. Then use this skill for general TypeScript guidance, including TypeScript embedded in other file formats. Combine it with more specific framework, testing, or library-focused skills when needed.
Prefer named intermediate values for function arguments
Do not pass function calls or other non-trivial expressions directly as arguments to another function. If an argument would be a call, awaited value, chained transform, inline conditional, or other derived expression, assign it to a clearly named const first and pass that variable instead.
Passing simple values directly is fine:
- identifiers
- property access
- primitive literals
- enum members and named constants
- simple object or array literals assembled from existing values
Only allow nesting for declarative validator or schema-builder DSL calls where the schema shape is the primary focus of the code. For example, Valibot calls such as v.string(), v.number(), v.optional(...), v.object(...), and v.pipe(...) are allowed to remain nested.
// Avoid nested calls in arguments
const activeReservation = getRedirectReservation()
navigateToReservation(activeReservation)
// Avoid hiding async work inside another call
const reservationPromise = getRedirectReservation()
await withMinimumDelay(reservationPromise, splashDelay)
// Avoid complex inline conditionals as arguments
const redirectTarget = hasReservation ? routes.stay : routes.checkIn
replaceRoute(redirectTarget)
// Allowed: declarative validator DSL
const reservationSchema = v.object({
slug: v.string(),
startDate: v.string(),
endDate: v.string()
})
Prefer flat interface structures
Keep interface declarations and named object type aliases to one level of named properties. When a property needs an object shape, extract that shape into a separate named interface and reference it from the parent type.
Apply this to direct object properties, arrays of objects, and nullable or union forms such as brand: { ... }, items: { ... }[], and brand: { ... } | null.
This rule covers type declarations only. It does not apply to runtime object literals, validator schemas, framework configuration objects, or library DSL values where the object shape is executable configuration rather than a reusable type contract.
// Avoid inline object shapes in interfaces
interface ItemDetailResponse {
brand: {
id: number;
name: string;
};
id: string;
}
// Prefer named nested contracts
interface ItemDetailBrand {
id: number;
name: string;
}
interface ItemDetailResponse {
brand: ItemDetailBrand;
id: string;
}
More from perdolique/workflow
pr-creator
Create GitHub pull requests from code changes via API or generate PR content in chat. Use when user wants to create/open/submit PR, mentions pull request/PR/merge request/code review, or asks to show/generate/display/output PR content in chat (give me PR, PR to chat, send PR to chat, etc).
56commit-creator
Create English conventional commit messages for the current changes. Use when the user wants to commit code, asks for a commit message, or needs monorepo scopes and version updates handled correctly.
47code-style-typescript
TypeScript style rules for writing, reviewing, and refactoring `.ts` code. Use when working on TypeScript formatting, semicolon conventions, object layout, function call structure, or interface definitions. Also use when reviewing or writing TypeScript interfaces, type aliases, or any nested object type shapes.
38markdownlint
Configure, manage, and troubleshoot markdownlint in projects. Use when user wants to setup/install/configure markdownlint, add/remove/modify linting rules, fix markdown validation issues, customize .markdownlint.yaml, update ignore patterns, integrate with tools (Husky, CI), or troubleshoot markdown linting errors. Use even when user mentions markdown formatting problems, quality issues, or style consistency without explicitly saying "markdownlint".
30playwright-e2e-testing
Write and maintain Playwright end-to-end tests for web apps. Use when the user asks for browser or E2E coverage, or for tests covering pages, routes, redirects, navigation, dialogs, authentication, or multi-step user flows, even if they do not explicitly mention Playwright. Also use for API mocking, fixtures, and Playwright-specific assertions.
15vitest-unit-testing
Write and maintain Vitest unit tests for TypeScript code. Use when the user needs unit coverage for utilities, services, or stores, or asks for Vitest-based tests with mocks, spies, and assertions.
14