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

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

Tämä asiakirja sisältää säännöt, joita on noudatettava koodia kirjoitettaessa.

Tavoitteena on, että koodipohja on johdonmukainen, helppolukuinen ja helppo ylläpitää.

Tässä mielessä on parempi olla hieman sanallisempi kuin liian ytimekäs.

Muista aina, että ihmiset lukevat koodia useammin kuin kirjoittavat sitä, erityisesti avoimen lähdekoodin projektissa, jossa kuka tahansa voi osallistua.

Monia sääntöjä ei ole määritelty tässä, mutta linterit tarkistavat ne automaattisesti.

## React

### Käytä toiminnallisia komponentteja

Käytä aina TSX-toiminnallisia komponentteja.

Älä käytä oletustasi `import` yhdessä `const`:n kanssa, sillä se on vaikeampi lukea ja vaikeampi ottaa käyttöön koodin täydennystoiminnolla.

```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>;
};
```

### Rekvisiitat

Luo rekvisiittatyyppi ja kutsu sitä `(ComponentName)Props`, jos sitä ei tarvitse viedä.

Käytä rekvisiittojen rakenteen purkamista.

```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>;
```

#### Vältä `React.FC` tai `React.FunctionComponent` käyttöä rekvisiittatyyppien määrittelyyn

```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 />
);
```

#### Ei yksittäistä muuttujapropin levitystä JSX-alkioissa

Vältä yksittäisen muuttujapropin levitystä JSX-elementeissä, kuten `{...props}`. Tämä käytäntö johtaa usein koodiin, joka on vähemmän luettavaa ja vaikeampaa ylläpitää, koska ei ole selvää, mitä rekvisiittoja komponentti vastaanottaa.

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

Perustelu:

- Yhdellä silmäyksellä on selvempää, mitä rekvisiittoja koodi välittää, mikä helpottaa ymmärtämistä ja ylläpitoa.
- Se auttaa estämään tiukan kytkennän komponenttien välillä niiden rekvisiittojen kautta.
- Lintityökalut helpottavat väärin kirjoitettujen tai käyttämättömien rekvisiittojen tunnistamista, kun listaat rekvisiitat suoraan.

## JavaScript

### Käytä tyhjän yhdistävää operaattoria `??`

```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';
```

### Käytä valinnaista ketjuttamista `?.`

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

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

## TypeScript

### Käytä `type` sen sijaan, että käyttäisit `interface`

Käytä aina `type` `interface`:n sijaan, koska ne melkein aina menevät päällekkäin ja `type` on joustavampi.

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

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

### Käytä merkkijono kirjaimellisia muodoksia enumien sijaan

[Merkkijonolitteraalit](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) ovat tapa käsitellä enum-muotoisia arvoja TypeScriptissä. Niitä on helpompi laajentaa Pict:llä ja Omit:illa, ja ne tarjoavat paremman kehittäjäkokemuksen, erityisesti koodin täydentämisessä.

Voit nähdä, miksi TypeScript suosittelee välttämään enumia [täällä](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 ja sisäiset kirjastot

Käytä koodegenin tuottamia enumia GraphQL:lle.

On myös parempi käyttää enumia käytettäessä sisäistä kirjastoa, jotta sisäisen kirjaston ei tarvitse antaa merkkijonolitteraalityyppiä, joka ei liity sisäiseen API:in.

Esimerkki:

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

setHotkeyScopeAndMemorizePreviousScope(
  RelationPickerHotkeyScope.RelationPicker,
);
```

## Tyylittely

### Käytä StyledComponents

Tyylitä komponentit [styled-componentsilla](https://emotion.sh/docs/styled).

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

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

Että tyylitetyille komponenteille luotaisiin tunnistettava ero "oikeiden" komponenttien kanssa, lisää etuliitteeksi "Styled".

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

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

### Teemaaminen

Teeman hyödyntäminen suurimmassa osassa komponenttien tyylittelyä on suositeltavaa.

#### Mittayksiköt

Vältä `px` tai `rem` arvojen suoraa käyttöä tyylitetyissä komponenteissa. Tarvittavat arvot ovat yleensä jo määritelty teemassa, joten niitä suositellaan käytettäväksi näihin tarkoituksiin.

#### Värit

Vältä uusien värien tuomista, käytä sen sijaan olemassa olevaa palettia teemasta. Jos kohtaamme tilanteen, jossa paletti ei vastaa, jätä kommentti, jotta tiimi voi korjata sen.

```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};
`;
```

## Ei-tyypin tuontien kieltämisen valvonta

Vältä tyyppituonteja. Tämän standardin valvomiseksi ESLint-sääntö tarkistaa ja raportoi kaikki tyyppituontien rikkomukset. Tämä auttaa säilyttämään johdonmukaisuutta ja luettavuutta TypeScript-koodissa.

```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';
```

### Miksi ei-tyypin tuonteja

- **Johdonmukaisuus**: Välttämällä tyyppituonteja ja käyttämällä yhtenäistä lähestymistapaa sekä tyyppi- että arvojen tuontiin, koodikanta pysyy johdonmukaisena moduulien tuontityylissä.

- **Readability**: No-type imports improve code readability by making it clear when you're importing values or types. Tämä vähentää epäselvyyttä ja helpottaa ymmärtämään tuontisymbolien tarkoitusta.

- **Maintainability**: It enhances codebase maintainability because developers can identify and locate type-only imports when reviewing or modifying code.

### ESLint sääntö

ESLint-sääntö, `@typescript-eslint/consistent-type-imports`, valvoo ei-tyyppituontistandardia. Tämä sääntö tuottaa virheitä tai varoituksia kaikista tyyppituontirikkomuksista.

Huomaa, että tämä sääntö koskee erityisesti harvinaisia erityistilanteita, joissa tahattomia tyyppituonteja tapahtuu. TypeScript itsessään kehottaa välttämään tätä käytäntöä, kuten sanotaan [TypeScript 3.8 -julkaisumuistiossa](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.

To ensure your code complies with this rule, make sure to run ESLint as part of your development workflow.
