概要:このチュートリアルでは、TypeScriptインターフェースとその使用方法について学び、型チェックを実施する方法を理解します。
TypeScriptインターフェース入門
TypeScriptインターフェースは、コード内の契約を定義します。また、型チェックのための明示的な名前を提供します。
簡単な例から始めましょう
function getFullName(person: {
firstName: string;
lastName: string
}) {
return `${person.firstName} ${person.lastName}`;
}
let person = {
firstName: 'John',
lastName: 'Doe'
};
console.log(getFullName(person));
Code language: TypeScript (typescript)
出力
John Doe
Code language: TypeScript (typescript)
この例では、TypeScriptコンパイラは、getFullName()
関数に渡す引数をチェックします。
引数にfirstName
とlastName
の2つのプロパティがあり、それらの型が文字列である場合、TypeScriptコンパイラはチェックを通過します。そうでない場合は、エラーを発行します。
関数引数の型注釈は、コードを読みづらくします。この問題に対処するために、TypeScriptはインターフェースの概念を導入しています。
以下は、2つの文字列プロパティを持つインターフェースPerson
を使用しています
interface Person {
firstName: string;
lastName: string;
}
Code language: CSS (css)
慣例により、インターフェース名はパスカルケースです。名前の単語を区切るために、大文字を1つ使用します。たとえば、Person
、UserProfile
、FullName
などです。
Person
インターフェースを定義した後、それを型として使用できます。たとえば、関数パラメータにインターフェース名で注釈を付けることができます
function getFullName(person: Person) {
return `${person.firstName} ${person.lastName}`;
}
let john = {
firstName: 'John',
lastName: 'Doe'
};
console.log(getFullName(john));
Code language: TypeScript (typescript)
コードは以前よりも読みやすくなりました。
コードをより簡潔にするために、JavaScriptのオブジェクト分割代入機能を使用できます
function getFullName({ firstName, lastName }: Person) {
return `${firstName} ${lastName}`;
}
Code language: JavaScript (javascript)
引数では、person
オブジェクトのプロパティを分割代入します
{ firstName, lastName }: Person
getFullName()
関数は、少なくともfirstName
とlastName
という名前の2つの文字列プロパティを持つオブジェクトを受け入れます。
たとえば、次のコードは4つのプロパティを持つオブジェクトを宣言しています
let jane = {
firstName: 'Jane',
middleName: 'K.',
lastName: 'Doe',
age: 22,
};
Code language: JavaScript (javascript)
jane
オブジェクトには、2つの文字列プロパティfirstName
とlastName
があるため、次のようにgetFullName()
関数に渡すことができます
let fullName = getFullName(jane);
console.log(fullName); // Jane Doe
Code language: JavaScript (javascript)
オプションのプロパティ
インターフェースにはオプションのプロパティを含めることができます。オプションのプロパティを宣言するには、宣言のプロパティ名の最後に疑問符(?
)を使用します。次のようにします
interface Person {
firstName: string;
middleName?: string;
lastName: string;
}
Code language: TypeScript (typescript)
この例では、Person
インターフェースには2つの必須プロパティと1つのオプションのプロパティがあります。
getFullName()
関数でPerson
インターフェースを使用する方法は次のとおりです
function getFullName(person: Person) {
if (person.middleName) {
return `${person.firstName} ${person.middleName} ${person.lastName}`;
}
return `${person.firstName} ${person.lastName}`;
}
Code language: TypeScript (typescript)
読み取り専用プロパティ
オブジェクトが最初に作成されたときにのみプロパティを変更できるようにする場合は、プロパティの名前の前にreadonly
キーワードを使用できます
interface Person {
readonly ssn: string;
firstName: string;
lastName: string;
}
let person: Person;
person = {
ssn: '171-28-0926',
firstName: 'John',
lastName: 'Doe',
};
Code language: TypeScript (typescript)
この例では、ssn
プロパティは変更できません
person.ssn = '171-28-0000';
Code language: TypeScript (typescript)
エラー
error TS2540: Cannot assign to 'ssn' because it is a read-only property.
Code language: TypeScript (typescript)
関数型
プロパティを持つオブジェクトを記述することに加えて、インターフェースを使用すると、関数型を表すことができます。
関数型を記述するには、型と戻り値の型を含むパラメータリストを含む関数シグネチャにインターフェースを割り当てます。例えば
interface StringFormat {
(str: string, isUpper: boolean): string
}
Code language: TypeScript (typescript)
これで、この関数型インターフェースを使用できます。
以下は、関数型の変数を宣言し、それに同じ型の関数値を割り当てる方法を示しています
let format: StringFormat;
format = function (str: string, isUpper: boolean) {
return isUpper ? str.toLocaleUpperCase() : str.toLocaleLowerCase();
};
console.log(format('hi', true));
Code language: TypeScript (typescript)
出力
HI
Code language: TypeScript (typescript)
パラメータ名は関数シグネチャと一致する必要はありません。次の例は上記の例と同等です
let format: StringFormat;
format = function (src: string, upper: boolean) {
return upper ? src.toLocaleUpperCase() : src.toLocaleLowerCase();
};
console.log(format('hi', true));
Code language: TypeScript (typescript)
StringFormat
インターフェースは、それを実装する関数のすべての呼び出し元が、必要な引数(文字列
とブール値
)を渡すことを保証します。
次のコードは、lowerCase
が2番目の引数を持たない関数に割り当てられている場合でも、完全に正常に機能します
let lowerCase: StringFormat;
lowerCase = function (str: string) {
return str.toLowerCase();
}
console.log(lowerCase('Hi', false));
Code language: TypeScript (typescript)
lowerCase()
関数が呼び出されたときに2番目の引数が渡されることに注意してください。
クラスタイプ
JavaまたはC#を使用したことがある場合、インターフェースの主な用途はクラス間の契約を定義することであることがわかります。
たとえば、次のJson
インターフェースは、任意のクラスによって実装できます
interface Json {
toJson(): string;
}
Code language: PHP (php)
以下は、Json
インターフェースを実装するクラスを宣言しています
class Person implements Json {
constructor(private firstName: string, private lastName: string) {}
toJson(): string {
return JSON.stringify(this);
}
}
Code language: TypeScript (typescript)
Person
クラスでは、Json
インターフェースのtoJson()
メソッドを実装しました。
次の例は、Person
クラスを使用する方法を示しています
let person = new Person('John', 'Doe');
console.log(person.toJson());
Code language: TypeScript (typescript)
出力
{"firstName":"John","lastName":"Doe"}
Code language: JSON / JSON with Comments (json)
まとめ
- TypeScriptインターフェースは、コード内の契約を定義し、型チェックのための明示的な名前を提供します。
- インターフェースには、オプションのプロパティまたは読み取り専用プロパティを含めることができます。
- インターフェースは関数型として使用できます。
- インターフェースは通常、無関係なクラス間の契約を結ぶクラスタイプとして使用されます。