サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

TypeScript入門 08: 型の互換性


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};  // エラー


作成者: 野中文雄
更新日: 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.