【型は命、anyは敵】 React + TypeScript のコーディング規約を一部晒す

この記事は、[Wano Group Advent Calendar 2021](https://qiita.com/advent-calendar/2021/wano-group) の記事です。

# 型は命、anyは敵？
「型は命、anyは敵」 とタイトルに書きましたが、anyが必要な場面ももちろんあると思います。避けるべきは不用意なanyによる型の握りつぶしです。
この前提をもとに可能な限り正しく型付けを行うことが、最大のコーディング規約です。

# Reactファイルのテンプレート
半分結論に近いですが、先にReactのファイルのテンプレートを晒します。
何かしらのComponentを作成するとき、とりあえずこれを書いています。

``` SampleCompnent.tsx
import React from 'react';

interface Props {
  className?: string;
}

const SampleComponent: React.VFC<Props> = ({ className }) => {
  return (
    <div className={className}>
      SampleComponent 
    </div>
  )
}

export default SampleComponent;
```

# コーディング規約

### 原則としてComponentは１ファイル１つにし、ファイル名とComponent名を一致させる
コードの見通しを良くするためです。
（まれに例外として、小さなComponentをファイル内に定義することはあります。）

``` SampleComponent.tsx
const SampleComponent: React.VFC<Props> = () => {} ;
```


### Component の export には `default export` を使い、 Named Exportしない
``` 
const SampleComponent: React.VFC<Props> = () => {} ;
export default SampleComponent;
```


### tsxファイルでは、`import { useEffect }` のような Named import はしない
import React するので、基本的に個別でのNamed Importはしないように揃えています。

```
// Good
import React from "react";

  React.useEffect(()=>{ /* ... */ },[]);

// Bad
import React, { useEffect } from "react";

  useEffect(()=>{ /* ... */ },[]);

```

### styled-componentsは使わない

material-ui を採用しており、基本的に [makeStyles](https://mui.com/styles/basics/#hook-api) を使っています。
頻度は低いですが、共通のClassを使いたい場合に共通のhookとして複数Componentから使い回すことも可能なのが利点です。

```
const useStyles = makeStyles(theme => {
  root: {
    marginTop: theme.spacing(2),
  },
});
```

### Component の props の型は明示的に宣言する
可読性向上が目的です。

```
// Good
interface Props {
  className?: string;
};
const Component: React.VFC<Props> = (props) => {};

// Bad
const Component = (props: { className?: string }) => {};
```

### 型の定義（特にProps）には `type` ではなく `interface` を使う
多くの場合、Propsはシンプルな型なので interfaceで定義可能だと思っています。
ジェネリクスや型推論が必要であったり、よほど複雑な型の場合はtypeを使うことは許容していますが、よりシンプルな型にする意識を保つことで可読性も保ちやすいと考えています。

```
// Good
interface Props {
  title: string,
  className?: string,
};

// Bad
type Props = {
  title: string
  className?: string,
};

// OK - ただし、他のComponentに依存してよいかなどはレビューで議論する
type Props = {
  title: string,
  className?: string,
} & Partial<React.ComponentProps<OtherComponent>>;
```

### Component の型定義には `FC` ではなく `VFC` を使う
`FC` を使うと、 `children` が optional として props に入ってしまいます。
`VFC` を使い、明示的に `children` の有無を指定することで、コーディングミスを減らすことが目的です。
同様の理由から、`PropsWithChildren` を使うことも避けています。

```
// Good
interface Props {
  className?: string;
  children: React.ReactNode;
};

const Component: React.VFC<Props> = ({ children, className }) => {};

// Bad
interface Props {
  className?: string;
};

const Component: React.FC<Props> = ({ children, className }) => {};
```

### props は destruct で受ける
`useEffect` などのhookの第二引数`deps`にpropsそのものを指定しないように。
`deps` で毎回　`props.` とアクセスしないで良いように。

```
// Good
const Component: React.VFC<Props> = ({ className }) => {};

// Bad
const Component: React.VFC<Props> = (props) => {};
```

# あとがき
ここに書いたものはあくまでも個人的なコーディング規約であり、パフォーマンスや可読性を万人に保証するものではありません。
ただし、できるだけベストプラクティスに近い形になるように心がけています。

初歩的なものばかりになってしまったので、いつか型に関するコーディング規約とTipsに関する第二弾を書きたいと思います。
↓こういう感じのとか。

```
interface PropsA {
  type: "typeA",
  content?: never;
};

interface PropsB {
  type: "typeB",
  content: React.ReactNode;
};

type Props = PropsA | PropsB;
```

TypeScriptの型システムを最大限活かすことで、Reactの安全に書くことができると思います。
もしも各項目でより良い型付けがあれば是非教えて下さい。