interface は「オブジェクトの設計図」
interface は、オブジェクトの「形(どんなプロパティを持つか)」を表す設計図です。
「このオブジェクトは、こういうプロパティを持っていて、その型はこうでなければならない」という“契約”を決めるものだと思ってください。
interface User {
id: number;
name: string;
email: string;
}
const userA: User = {
id: 1,
name: "Taro Yamada",
email: "taro@example.com",
};
TypeScriptここで User は、「id: number, name: string, email: string を必ず持つオブジェクト」というルールです。
このルールから外れるオブジェクトを代入しようとすると、TypeScript がコンパイル時に止めてくれます。
interface の基本構文と使い方
オブジェクトの形を定義する
interface Person {
name: string;
age: number;
}
function greet(person: Person) {
console.log(`Hello, ${person.name} (${person.age})`);
}
greet({ name: "Taro", age: 20 });
TypeScriptinterface Person { ... } で「Person という名前の“形”」を定義し、person: Person で「この引数はその形を満たすオブジェクトでなければならない」と宣言しています。
ここで重要なのは、interface 自体は「中身の処理」ではなく「形だけ」を定義するという点です。
「どんなプロパティ名があって、その型は何か」だけを決めます。
プロパティの必須・任意・readonly
必須プロパティ
何も印を付けなければ、そのプロパティは「必須」です。
interface User {
id: number;
name: string;
}
const u1: User = { id: 1, name: "Taro" }; // OK
const u2: User = { id: 1 }; // エラー(name が足りない)
TypeScript「このプロパティは絶対に必要」という仕様を、型として表現できます。
オプションプロパティ(?)
? を付けると「なくてもよい」プロパティになります。
interface User {
id: number;
name: string;
age?: number;
}
const u1: User = { id: 1, name: "Taro" }; // OK
const u2: User = { id: 1, name: "Hanako", age: 18 }; // OK
TypeScriptage? は「age は number かもしれないし、そもそも存在しないかもしれない」という意味です。
使う側では「ないかもしれない」ことを意識してコードを書く必要があります。
readonly プロパティ
readonly を付けると、「一度値を入れたら書き換え禁止」のプロパティになります。
interface Config {
readonly env: string;
readonly debug: boolean;
}
const config: Config = {
env: "dev",
debug: true,
};
// config.env = "prod"; // エラー:読み取り専用
TypeScript「設定値のように、あとから変えてほしくないもの」を表現するときにとても役立ちます。
interface を使うとコードがどう良くなるか
「形」を名前で共有できる
interface User {
id: number;
name: string;
}
function printUser(user: User) { ... }
function saveUser(user: User) { ... }
function deleteUser(user: User) { ... }
TypeScript同じ { id: number; name: string } という形を、User という名前で共有できます。
もしあとから「name を fullName に変えたい」となっても、interface User を1か所直せば、
それを使っている関数すべてに変更が反映されます。
「このオブジェクトはこういうものだ」という意図が伝わる
interface LoginRequest {
email: string;
password: string;
}
function login(req: LoginRequest) { ... }
TypeScriptただ { email: string; password: string } と書くよりも、LoginRequest という名前が付くだけで、「これはログイン用のリクエストだ」と一目で分かります。
「意味のある名前をつけた設計図」として interface を使うイメージです。
type と interface の関係をざっくりだけ
どちらも「オブジェクトの形」を表現できる
TypeScript では、オブジェクトの型は interface でも type でも書けます。
interface Person {
name: string;
age: number;
}
type Person2 = {
name: string;
age: number;
};
TypeScriptこの2つは、基本的には同じ意味です。
初心者のうちは、「オブジェクトの形に名前をつけるなら、とりあえず interface でも type でもいい」くらいの理解で十分です。
より細かい違い(拡張の仕方、宣言マージなど)は、
interface に慣れてきてから、必要になったときに覚えればOKです。
初心者がまず掴んでおきたい interface の感覚
interface の本質は、たったひとつです。
「このオブジェクトは、こういうプロパティを持っていて、その型はこうであるべきだ」という契約を、コードの外ではなく“型”として書き下すもの。
だからこそ、
- ユーザー情報
- 商品情報
- APIレスポンス
- 設定オブジェクト
のような「意味のあるまとまり」を見つけたら、
一度 interface 名前 { ... } で形を定義してみるといいです。
「バラバラのオブジェクト」から「設計図に基づいたオブジェクト」に変わった瞬間、
コードの読みやすさと安全性が、かなりはっきり変わってきます。
