---
title: Stijlgids
image: /images/user-guide/notes/notes_header.png
---

<Frame>
  <img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>

Dit document bevat de regels die moeten worden gevolgd bij het schrijven van code.

Het doel hier is om een consistente codebasis te hebben, die gemakkelijk te lezen en te onderhouden is.

Hiervoor is het beter om iets uitgebreider te zijn dan te beknopt.

Always keep in mind that people read code more often than they write it, specially on an open source project, where anyone can contribute.

Er zijn veel regels die hier niet zijn gedefinieerd, maar die automatisch worden gecontroleerd door linters.

## React

### Gebruik functionele componenten

Gebruik altijd TSX functionele componenten.

Do not use default `import` with `const`, because it's harder to read and harder to import with code completion.

```tsx
// ❌ 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>;
};
```

### Props

Maak het type van de props en noem het `(ComponentName)Props` als het niet nodig is om het te exporteren.

Gebruik props destructuring.

```tsx
// ❌ 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>;
```

#### Weerhoud u ervan `React.FC` of `React.FunctionComponent` te gebruiken om proptypen te definiëren

```tsx
/* ❌ - 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
/* ✅ - 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 />
);
```

#### Geen enkele variabele prop-spreading in JSX elementen

Vermijd het gebruik van enkele variabele prop-spreading in JSX elementen, zoals `{...props}`. Deze praktijk resulteert vaak in code die minder leesbaar en moeilijker te onderhouden is, omdat het onduidelijk is welke props de component ontvangt.

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

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

Motivatie:

- Op het eerste gezicht is het duidelijker welke props de code doorgeeft, waardoor het gemakkelijker te begrijpen en te onderhouden is.
- Het helpt om een sterke koppeling tussen componenten via hun props te voorkomen.
- Lint-tools maken het gemakkelijker om verkeerd gespelde of ongebruikte props te identificeren wanneer je props expliciet opsomt.

## JavaScript

### Gebruik de nullish-coalescing operator `??`

```tsx
// ❌ 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';
```

### Gebruik optionele chaining `?.`

```tsx
// ❌ Bad 
onClick && onClick();

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

## TypeScript

### Gebruik `type` in plaats van `interface`

Gebruik altijd `type` in plaats van `interface`, omdat ze bijna altijd overlappen, en `type` flexibeler is.

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

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

### Gebruik stringliterals in plaats van enums

[Stringliterals](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) zijn de standaardmanier om enum-achtige waarden in TypeScript aan te pakken. Ze zijn gemakkelijker uit te breiden met Pick en Omit en bieden een betere ontwikkelaarservaring, vooral met codeaanvulling.

U kunt hier zien waarom TypeScript aanbeveelt om enums te vermijden [hier](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).

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

let color = Color.Red;
```

```tsx
// ✅ Good, utilizes a string literal

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

#### GraphQL en interne bibliotheken

U moet enums gebruiken die GraphQL codegen genereert.

Het is ook beter om een enum te gebruiken bij het gebruik van een interne bibliotheek, zodat de interne bibliotheek geen stringliteral type hoeft bloot te leggen dat niet gerelateerd is aan de interne API.

Voorbeeld:

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

setHotkeyScopeAndMemorizePreviousScope(
  RelationPickerHotkeyScope.RelationPicker,
);
```

## Styling

### Gebruik StyledComponents

Style de componenten met [styled-components](https://emotion.sh/docs/styled).

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

```tsx
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

Prefix styled components met "Styled" om ze te onderscheiden van "echte" componenten.

```tsx
// ❌ Bad
const Title = styled.div`
  color: red;
`;
```

```tsx
// ✅ Good
const StyledTitle = styled.div`
  color: red;
`;
```

### Thema's

Het gebruik van het thema voor de meerderheid van de component styling is de voorkeursaanpak.

#### Meeteenheden

Vermijd het gebruik van `px` of `rem` waarden rechtstreeks in de gestylede componenten. De benodigde waarden zijn over het algemeen al gedefinieerd in het thema, dus het is aan te raden om het thema voor deze doeleinden te gebruiken.

#### Kleuren

Onthoud u van het introduceren van nieuwe kleuren; in plaats daarvan moet de bestaande palet van het thema gebruikt worden. Mocht er een situatie zijn waarin het palet niet overeenkomt, laat dan een opmerking achter zodat het team het kan corrigeren.

```tsx
// ❌ 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
// ✅ 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};
`;
```

## Afdwingen van geen-type imports

Vermijd type imports. Om deze standaard af te dwingen, controleert een ESLint-regel op type imports en rapporteert die. Dit helpt om consistentie en leesbaarheid in de TypeScript code te handhaven.

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

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

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

### Waarom geen-type imports

- **Consistentie**: Door type imports te vermijden en een enkele benadering te gebruiken voor zowel type- als waarde-imports, blijft de codebasis consistent in zijn module-importstijl.

- **Leesbaarheid**: Geen-type imports verbeteren de codeleesbaarheid door duidelijk te maken wanneer je waarden of typen importeert. Dit vermindert ambiguïteit en maakt het gemakkelijker om het doel van geïmporteerde symbolen te begrijpen.

- **Onderhoudbaarheid**: Het verbetert de onderhoudbaarheid van de codebasis omdat ontwikkelaars type-only imports kunnen identificeren en lokaliseren tijdens het beoordelen of wijzigen van code.

### ESLint-regel

An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. Deze regel genereert fouten of waarschuwingen voor elke overtreding van type imports.

Merk op dat deze regel specifiek zeldzame randgevallen adresseert waar onbedoelde type imports voorkomen. TypeScript zelf ontmoedigt deze praktijk, zoals vermeld in de [TypeScript 3.8 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In de meeste situaties is het niet nodig om type-only imports te gebruiken.

Om ervoor te zorgen dat uw code aan deze regel voldoet, moet u ESLint als onderdeel van uw ontwikkelworkflow uitvoeren.
