型の互換性

TypeScriptは構造的型システム(structural typing)を採用しており、型の名前ではなく中身(構造)で互換性を判断します。

✅ 互換性のある例

type Point2D = { x: number; y: number };
type Point3D = { x: number; y: number; z: number };

const point3D: Point3D = { x: 0, y: 0, z: 0 };
const point2D: Point2D = point3D; // OK: point3Dはpoint2Dの構造を満たしている

❌ 互換性のない例(不足するプロパティ)

const point2D: Point2D = { x: 0, y: 0 };
const point3D: Point3D = point2D; // エラー: 'z' がない

🧠 テクニック集

1. as const でリテラル型を保つ

const direction = 'left' as const;
// typeof direction === 'left'

2. Readonly / readonly で不変性を担保

type User = {
  readonly id: number;
  name: string;
};

const u: User = { id: 1, name: "Alice" };
u.id = 2; // エラー: 読み取り専用

🛑 型互換性に注意すべきパターン

1. 関数のパラメータの逆変性(バリアント)

type Animal = { name: string };
type Dog = { name: string; bark: () => void };

let animal: (a: Animal) => void;
let dog: (d: Dog) => void;

animal = dog; // エラー(--strictFunctionTypes 有効時)
dog = animal; // OK

2. オプションと必須プロパティの互換性

type A = { x: number };
type B = { x?: number };

const a: A = { x: 1 };
const b: B = a; // OK
// const a2: A = b; // エラー: x がある保証がない

コメントを残す 0

Your email address will not be published. Required fields are marked *