HTML5テクニカルノート
TypeScript入門 08: 型の互換性
- ID: FN1609009
- Technique: HTML5 / JavaScript
- Package: TypeScript 2.0.3
TypeScriptは型づけできることを大きな特長としています。型が合うか合わないかをどのように決めているのかについて、かいつまんでご説明します。詳しい内容については「TypeScript: 型の互換性」をお読みください。
01 インタフェースと型づけ
インタフェースはつぎのようにキーワードimplements
でクラスに実装すると、定められたプロパティをその型で定めなければなりません(「TypeScript入門 04: オブジェクト型リテラルとインタフェースを使う」03「インタフェースを定める」参照)。
class Point implements IPoint { constructor(public x: number, public y: number) {} } interface IPoint { x: number; y: number; }
インタフェース(IPoint)は、つぎのように変数(point)の型づけにも用いられます。インタフェースを実装したクラス(Point)のインスタンスは、もちろん変数に納められます。
let point: IPoint point = new Point(0, 0);
02 プロパティとその型で互換性を調べる
TypeScriptでは型が合うかどうかは、定められた型のプロパティ(メンバー)を照合して確かめます。同じ名前のプロパティを同じ型でもっていれば、型は合っているとされるのです。インタフェースの実装やクラスの継承を求めません。たとえば、つぎのクラス(Point3D)は、前掲クラス(Point)を継承しませんし、インタフェース(IPoint)も実装していません。
class Point3D { constructor(public x: number, public y: number, public z: number) {} }
けれども、つぎのようにインタフェース(IPoint)が定めるプロパティ(xとy)を同じ型(number)で備えていれば、コードにエラーは起こりません。また、型づけにないプロパティ(z)があっても構わないのです。
let point: IPoint point = {x: 0, y: 0}; point = new Point3D(0, 0, 0);
関数の引数への型づけについても同じです。たとえば、つぎのように関数(getDistance2D)の引数の型にインタフェース(IPoint)を定めたとします。
function getDistance2D(point2d: IPoint): number { var square: number = point2d.x * point2d.x + point2d.y * point2d.y; return Math.sqrt(square); }
インタフェースの定めるプロパティを同じ型で備えていれば、インタフェースの実装やクラスの継承は問わず、型は合っているとみなされます。テスト用に定めたクラスとインタフェースおよび関数のTypeScriptコードをご参考までに以下にまとめました(コード001)。
var length: number = getDistance2D(new Point3D(1, Math.sqrt(3), 0)); console.log(length); // 1.9999999999999998
コード001■クラスとインタフェースおよび関数の定め
class Point implements IPoint {
constructor(public x: number, public y: number) {}
}
interface IPoint {
x: number;
y: number;
}
class Point3D {
constructor(public x: number, public y: number, public z: number) {}
}
function getDistance2D(point2d: IPoint): number {
var square: number = point2d.x * point2d.x + point2d.y * point2d.y;
return Math.sqrt(square);
}
03 型推論
TypeScriptは変数に型づけできることが大きな特長です。さらに、型づけしなくとも、変数宣言に初期値を与えれば、推論から型が定まります(詳しくは「TypeScript: 型推論」参照)。たとえば、以下のように変数(value)の初期値に文字列を納めれば型はstring
とみなされ、文字列以外のデータで上書きしようとすると、つぎのようなエラーが示されます。
Type 'number' is not assignable to type 'string'.
let value = 'fumio'; value = 1; // エラー
変数の初期値にオブジェクトを与えた場合も、そのクラスで型づけされます。前項と同じく、備わるプロパティとその型で、合うか合わないかが決まります。備わるプロパティが合致すればよく、その他のプロパティは問われません。けれど、足りなければつぎのようなエラーになります。
Type '{ x: number; }' is not assignable to type 'Point'. Property 'y' is missing in type '{ x: number; }'.
let point = new Point(0, 0); point = {x: 0, y: 0}; point = new Point3D(0, 0, 0); point = {x: 0}; // エラー
- TypeScript: とにかくJavaScriptファイルをビルドしてみる
- TypeScript入門 01: Visual Studio CodeでTypeScriptのコードを書く
- TypeScript入門 02: publicとprivateおよびstatic
- TypeScript入門 03: クラスを継承して使う
- TypeScript入門 04: オブジェクト型リテラルとインタフェースを使う
- TypeScript入門 05: get/setアクセサをを使う
- TypeScript入門 06: メソッド引数のデフォルト値と省略および定数を定める
- TypeScript入門 07: ブロックスコープに変数を宣言する ー let
- TypeScript入門 09: アロー関数式
- TypeScript入門 10: モジュール ー exportとimport
- TypeScript入門 11: 名前空間 ー namespace
- TypeScript入門 12: デコレータ(Decorator)を使う
作成者: 野中文雄
更新日: 2017年6月2日 03「型推論」に「TypeScript: 型推論」の参照を追加。
更新日: 2017年5月31日「TypeScript: 型の互換性」の参照を追加。
更新日: 2016年9月23日 TypeScriptのバージョンを2.0.3に更新。
作成日: 2016年9月17日
Copyright © 2001-2017 Fumio Nonaka. All rights reserved.