packages/docs/docs/contributing/code-style.md
This guide outlines the coding conventions and style guidelines for contributing to Actual Budget. Following these guidelines helps maintain consistency and code quality across the codebase.
type over interface: Use type aliases instead of interfaces when possibleenum: Use objects or maps instead of enumsany or unknown: Only use when absolutely necessarypackages/loot-core/src/types/ for existing type definitionssatisfies over as or ! for type narrowingisLoaded, hasError)function keyword for pure functionsReact.FunctionComponent or React.FC: Type props directlyReact.* patterns: Use named imports instead (e.g., import { useState } from 'react')import { type ComponentType } from 'react';
// ... other imports
type MyComponentProps = {
prop1: string;
prop2: number;
};
export function MyComponent({ prop1, prop2 }: MyComponentProps) {
// Component logic
return (
// JSX
);
}
Use custom hooks from src/hooks instead of importing directly from react-router or react-redux:
useNavigate() from src/hooks (not react-router)useDispatch(), useSelector(), useStore() from src/redux (not react-redux)satisfies for type narrowing: Prefer satisfies over type assertions<Link> instead of <a> tags: For internal navigationcondition && <Component />).api, .web, or .electron directlyloot-core for platform-specific code@actual-app/web/* imports in loot-core: Don't import from web package in coreimport { type ComponentType } from 'react';
// ... other imports
type MyComponentProps = {
// Props definition
};
export function MyComponent({ prop1, prop2 }: MyComponentProps) {
// Component logic
return (
// JSX
);
}
import { describe, it, expect, beforeEach } from 'vitest';
// ... imports
describe('ComponentName', () => {
it('should behave as expected', () => {
// Test logic
expect(result).toBe(expected);
});
});
Trans component: Prefer Trans component instead of t() function when possibleyarn generate:i18n to generate translation filesBefore committing changes, ensure:
yarn typecheck passesyarn lint:fix has been runtype over interface