> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Руководство по стилю

Этот документ включает правила, которые нужно соблюдать при написании кода.

Цель заключается в обеспечении однородности кода, который будет легко читать и поддерживать.

Для этого лучше быть немного более многословными, чем слишком краткими.

Всегда помните, что код читают чаще, чем пишут, особенно в проекте с открытым исходным кодом, в который может внести вклад кто угодно.

Существует много правил, которые здесь не описаны, но автоматически проверяются линтерами.

## React

### Используйте функциональные компоненты.

Всегда используйте функциональные компоненты TSX.

Не используйте стандартный `import` с `const`, так как это сложнее для чтения и импорта с автозаполнением кода.

```tsx theme={null}
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
  return <div>Hello World</div>;
};

export default MyComponent;

// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
  return <div>Hello World</div>;
};
```

### Свойства

Создайте тип пропсов и назовите его `(ComponentName)Props`, если нет необходимости экспортировать его.

Используйте деструктуризацию пропсов.

```tsx theme={null}
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;

// ✅ Good, type
type MyComponentProps = {
  name: string;
};

export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```

#### Воздержитесь от использования `React.FC` или `React.FunctionComponent` для определения типов пропсов.

```tsx theme={null}
/* ❌ - Bad, defines the component type annotations with `FC`
 *    - With `React.FC`, the component implicitly accepts a `children` prop
 *      even if it's not defined in the prop type. This might not always be
 *      desirable, especially if the component doesn't intend to render
 *      children.
 */
const EmailField: React.FC<{
  value: string;
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
```

```tsx theme={null}
/* ✅ - Good, a separate type (OwnProps) is explicitly defined for the
 *      component's props
 *    - This method doesn't automatically include the children prop. If
 *      you want to include it, you have to specify it in OwnProps.
 */
type EmailFieldProps = {
  value: string;
};

const EmailField = ({ value }: EmailFieldProps) => (
  <TextInput value={value} disabled fullWidth />
);
```

#### Нет разворачивания пропсов одиночной переменной в JSX-элементах.

Избегайте спреда пропсов из одной переменной в JSX-элементах, например `{...props}`. Подобная практика часто приводит к менее читаемому и сложному в поддержке коду, так как непонятно, какие пропсы принимает компонент.

```tsx theme={null}
/* ❌ - Bad, spreads a single variable prop into the underlying component
 */
const MyComponent = (props: OwnProps) => {
  return <OtherComponent {...props} />;
}
```

```tsx theme={null}
/* ✅ - Good, Explicitly lists all props
 *    - Enhances readability and maintainability
 */
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
  return <OtherComponent {...{ prop1, prop2, prop3 }} />;
};
```

Обоснование:

* С первого взгляда становится яснее, какие пропсы передаются в коде, что делает его легче понятным и поддерживаемым.
* Это помогает предотвратить жесткое связывание между компонентами через их пропсы.
* Инструменты для анализа кода облегчают обнаружение опечаток или неиспользуемых пропсов при явном перечислении пропсов.

## JavaScript

### Используйте оператор нулевого слияния `??`

```tsx theme={null}
// ❌ Bad, can return 'default' even if value is 0 or ''
const value = process.env.MY_VALUE || 'default';

// ✅ Good, will return 'default' only if value is null or undefined
const value = process.env.MY_VALUE ?? 'default';
```

### Используйте опциональную цепочку `?.`

```tsx theme={null}
// ❌ Bad
onClick && onClick();

// ✅ Good
onClick?.();
```

## TypeScript

### Используйте `type` вместо `interface`

Всегда используйте `type` вместо `interface`, так как они почти всегда пересекаются, а `type` более гибок.

```tsx theme={null}
// ❌ Bad
interface MyInterface {
  name: string;
}

// ✅ Good
type MyType = {
  name: string;
};
```

### Используйте строковые литералы вместо перечислений.

[Строковые литералы](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) - это основной способ обработки значений, напоминающих перечисление, в TypeScript. Их проще расширять с помощью Pick и Omit, и они обеспечивают более удобную работу разработчика, особенно благодаря автодополнению кода.

Вы можете увидеть, почему TypeScript рекомендует избегать перечислений [здесь](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).

```tsx theme={null}
// ❌ Bad, utilizes an enum
enum Color {
  Red = "red",
  Green = "green",
  Blue = "blue",
}

let color = Color.Red;
```

```tsx theme={null}
// ✅ Good, utilizes a string literal

let color: "red" | "green" | "blue" = "red";
```

#### GraphQL и внутренние библиотеки

Вы должны использовать перечисления, которые генерирует кодогенератор GraphQL.

Также лучше использовать перечисление при использовании внутренней библиотеки, чтобы она не требовала явного указания типа строкового литерала, не связанного с внутренним API.

Пример:

```TSX theme={null}
const {
  setHotkeyScopeAndMemorizePreviousScope,
  goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();

setHotkeyScopeAndMemorizePreviousScope(
  RelationPickerHotkeyScope.RelationPicker,
);
```

## Стилизация

### Использование StyledComponents

Стилизуйте компоненты с помощью [Linaria styled](https://github.com/callstack/linaria).

```tsx theme={null}
// ❌ Bad
<div className="my-class">Hello World</div>
```

```tsx theme={null}
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

Добавляйте префикс "Styled" к стилизованным компонентам, чтобы отличать их от "реальных" компонентов.

```tsx theme={null}
// ❌ Bad
const Title = styled.div`
  color: red;
`;
```

```tsx theme={null}
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

### Темизация

Использование темы для большинства стилевых компонентов является предпочтительным подходом.

#### Единицы измерения

Избегайте использования значений `px` или `rem` напрямую в стилизованных компонентах. Необходимые значения обычно уже определены в теме, поэтому рекомендуется использовать тему для этих целей.

#### Цвета

Избегайте введения новых цветов; используйте существующую палитру из темы. Если палитра не соответствует, оставьте комментарий, чтобы команда могла это исправить.

```tsx theme={null}
// ❌ Bad, directly specifies style values without utilizing the theme
const StyledButton = styled.button`
  color: #333333;
  font-size: 1rem;
  font-weight: 400;
  margin-left: 4px;
  border-radius: 50px;
`;
```

```tsx theme={null}
// ✅ Good, utilizes the theme
const StyledButton = styled.button`
  color: ${({ theme }) => theme.font.color.primary};
  font-size: ${({ theme }) => theme.font.size.md};
  font-weight: ${({ theme }) => theme.font.weight.regular};
  margin-left: ${({ theme }) => theme.spacing(1)};
  border-radius:  ${({ theme }) => theme.border.rounded};
`;
```

## Запрещение импорта типов

Избегайте импорта типов. Чтобы обеспечить соблюдение этого стандарта, правило Oxlint проверяет и сообщает о любых импортах с ключевым словом type. Это помогает сохранить согласованность и читаемость кода TypeScript.

```tsx theme={null}
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';

// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';

// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```

### Почему избегать импорта типов

* **Согласованность**: Избегая импорта типов и используя единый подход для импорта как типов, так и значений, кодовая база остается согласованной в стиле импорта модулей.

* **Читаемость**: Избегающий импорт типов улучшает читаемость кода, делая ясным, когда вы импортируете значения или типы. Это снижает двусмысленность и облегчает понимание назначения импортируемых символов.

* **Поддерживаемость**: Это повышает поддерживаемость кодовой базы, поскольку разработчики могут идентифицировать и находить импорты только типов при просмотре или изменении кода.

### Правило Oxlint

Правило Oxlint `typescript/consistent-type-imports` обеспечивает соблюдение стандарта импортов без ключевого слова type. Это правило создаст ошибки или предупреждения для всех нарушений импорта типов.

Обратите внимание, что это правило касается редких крайних случаев, когда случаются непреднамеренные импорты типов. Сам TypeScript не рекомендует эту практику, как указано в [примечаниях к выпуску TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). В большинстве случаев вам не нужно использовать импорты только типов.

Чтобы гарантировать соответствие вашего кода этому правилу, убедитесь, что вы запускаете Oxlint как часть вашего рабочего процесса разработки.
