5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RCC (立命館コンピュータークラブ)Advent Calendar 2024

Day 11

【Next.js/React】結局PropsではTypeとInterfaceどっちを使えばいいの?(TypeScriptにおけるTypeとInterfaceの違いとは?)

Posted at

結論

ずばり結論からいうと
どちらでもいいからプロジェクトを始めるときにどちらを使うのか決めること
結局はどちらにも向いていること、向いていないことがあるため、それぞれを理解し、場合によって使い分ける必要があります。本記事ではその理解ができればいいと思っています。

はじめに

ReactでTypeScriptを組み合わせて開発を行う際、コンポーネントのPropsを定義する方法としてtypeinterfaceの2つがあります。どちらを使うべきか迷ったことはありませんか?また、それぞれの違いやメリット・デメリットについて深く理解しているでしょうか。

本記事では、typeinterfaceの違いや長所と短所を詳しく解説し、最終的にどちらを使うべきかについて考察します。

一応Next.jsの公式のドキュメントではinterfaceを推奨しているようですが、Use interface till you need typeと言われているくらい、とりあえずはinterfaceでいいよという弱い推奨のようです

typeinterfaceの違い

まずは、TypeScriptでのtypeinterfaceの基本的な違いを理解しましょう。

type(型エイリアス)

typeは型エイリアスを定義するために使用します。これにより、より複雑な型をシンプルな名前で表現できます。

type User = {
  name: string;
  age: number;
};

interface

interfaceはオブジェクトの構造(形状)を定義するために使用します。プロパティやメソッドの型を指定できます。

interface User {
  name: string;
  age: number;
}

メリットとデメリット

typeのメリット

  1. 柔軟性が高い

    • ユニオン型やタプル型など、複雑な型の定義が可能です。
    type Status = 'success' | 'error' | 'loading';
    
  2. プリミティブ型やジェネリック型の定義

    • 型のエイリアスとして使用でき、コードの可読性を高めます。
    type ID = string | number;
    
  3. コンポジションが容易

    • 型の合成が簡単で、複数の型を組み合わせて新しい型を作成できます。
    type Person = {
      name: string;
    };
    type Employee = Person & {
      employeeId: number;
    };
    

typeのデメリット

  1. 宣言のマージができない

    • 同じ名前で複数のtypeを宣言するとエラーになります。
    type User = {
      name: string;
    };
    
    // エラー: 既に存在する型名を再宣言できない
    type User = {
      age: number;
    };
    
  2. 拡張性がやや低い

    • 型の拡張がinterfaceに比べて直感的でない場合があります。

interfaceのメリット

  1. 宣言のマージが可能

    • 同じ名前のinterfaceを複数回宣言すると、自動的にマージされます。
    interface User {
      name: string;
    }
    
    interface User {
      age: number;
    }
    
    // Userは{name: string; age: number;}として扱われる
    
  2. クラスの実装を強制できる

    • クラスに対してimplementsを使用し、特定のプロパティやメソッドの実装を要求できます。
    interface Serializable {
      serialize(): string;
    }
    
    class User implements Serializable {
      serialize() {
        return JSON.stringify(this);
      }
    }
    
  3. 拡張が容易

    • extendsを使用して既存のinterfaceを拡張できます。
    interface Person {
      name: string;
    }
    
    interface Employee extends Person {
      employeeId: number;
    }
    

interfaceのデメリット

  1. 柔軟性が低い

    • プリミティブ型のエイリアスやユニオン型、タプル型の定義が直接できません。
    // エラー: 'interface'でユニオン型を定義できない
    interface Status = 'success' | 'error' | 'loading';
    
  2. 型の合成がやや複雑

    • 複数のinterfaceを組み合わせる場合、&を使用する必要があります。

ReactのProps定義での使い分け

typeでのProps定義

type ButtonProps = {
  label: string;
  onClick: () => void;
};

const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
  <button onClick={onClick}>{label}</button>
);

interfaceでのProps定義

interface ButtonProps {
  label: string;
  onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
  <button onClick={onClick}>{label}</button>
);

どちらを使うべきか?

結論

私はPropsの定義にはtypeを使うことを推奨します。

理由

  • 柔軟性が高い: ユニオン型やタプル型など、複雑な型を定義しやすいため。
  • 堅牢性: 同じ名前のtypeは存在することがなく、

また、拡張することがあまりないため、ライブラリ開発などで型を拡張する必要がある場合などの例外を除いては、typeの方がいいと感じた。

しかし、結局一番大切なのは

typeinterfaceどちらを使うかプロジェクトごとに一貫性を持つこと

まとめ

  • Propsの定義にはtypeを使用するのがおすすめ
    • 柔軟性が高く、複雑な型の表現に適しているため。
  • interfaceはクラスの実装やライブラリ開発で使用する
    • 宣言のマージや拡張が必要な場合に有用。
  • 一貫性を持つことが重要
    • チームやプロジェクト内でtypeinterfaceの使い分け方針を統一すると、可読性とメンテナンス性が向上します。

おわりに

今回は、私がプロジェクトに関わる中で抱いたPropsではtypeinterfaceは使うのがいいのか?何が違うのか調べた結果を書きました。これについてはかなり意見がわかれる論争となる題材だと思っています。**ご意見やご質問がありましたら、ぜひコメントでお知らせください!**それではみなさん,いいエンジニアライフを〜👋

参考資料

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?