TypeScriptインターフェース

概要:このチュートリアルでは、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 DoeCode language: TypeScript (typescript)

この例では、TypeScriptコンパイラは、getFullName()関数に渡す引数をチェックします。

引数にfirstNamelastNameの2つのプロパティがあり、それらの型が文字列である場合、TypeScriptコンパイラはチェックを通過します。そうでない場合は、エラーを発行します。

関数引数の型注釈は、コードを読みづらくします。この問題に対処するために、TypeScriptはインターフェースの概念を導入しています。

以下は、2つの文字列プロパティを持つインターフェースPersonを使用しています

interface Person {
    firstName: string;
    lastName: string;
}Code language: CSS (css)

慣例により、インターフェース名はパスカルケースです。名前の単語を区切るために、大文字を1つ使用します。たとえば、PersonUserProfileFullNameなどです。

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()関数は、少なくともfirstNamelastNameという名前の2つの文字列プロパティを持つオブジェクトを受け入れます。

たとえば、次のコードは4つのプロパティを持つオブジェクトを宣言しています

let jane = {
  firstName: 'Jane',
  middleName: 'K.',
  lastName: 'Doe',
  age: 22,
};Code language: JavaScript (javascript)

janeオブジェクトには、2つの文字列プロパティfirstNamelastNameがあるため、次のようにgetFullName()関数に渡すことができます

let fullName = getFullName(jane);
console.log(fullName); // Jane DoeCode 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)

出力

HICode 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インターフェースは、コード内の契約を定義し、型チェックのための明示的な名前を提供します。
  • インターフェースには、オプションのプロパティまたは読み取り専用プロパティを含めることができます。
  • インターフェースは関数型として使用できます。
  • インターフェースは通常、無関係なクラス間の契約を結ぶクラスタイプとして使用されます。
このチュートリアルは役に立ちましたか?