Created by Github action --------- Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: github-actions <github-actions@twenty.com>
296 lines
8.9 KiB
Plaintext
296 lines
8.9 KiB
Plaintext
---
|
|
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.
|