海未「それではインターフェイスの話を始めましょう」
穂乃果「あれ、意外と元気だ」
ことり「海未ちゃんね、だんだん責めても動じなくなってきて・・・」
穂乃果「あー、毎度のことで順応してきたんだ・・・」
海未「インターフェイスという概念は、JavaやC#を知っている人にとっては馴染みのあるものでしょう。実装を持たない型定義です」
穂乃果「実装を持たない・・・型定義・・・?」
海未「まず、このコードを見てください」
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46  | 
						class SchoolIdol {     constructor(         name: string,         age: number,         school: string     ) {}     sing() {         console.log('Singing!!');     }     dance() {         console.log('Dancing!!');     } } class ProfessionalIdol {     constructor(         name: string,         age: number,         production: string     ) {}     sing() {         console.log('Singing!!');     }     talk() {         console.log('Talking!!')     } } class Alpaca {     constructor(         age: number     ) {}     bleat() {         console.log('meeeeeeeeeeeeeeee');     } } var honoka = new SchoolIdol('Honoka Kosaka', 16, 'Otonokizaka High'); var uzuki = new ProfessionalIdol('Uziki Shimamura', 17, '346Pro'); var alpaca = new Alpaca(10);  | 
					
海未「似たようなコードは何度も出てきた気がしますが、クラスが3つ普通に定義されていますね」
ことり「アルパカさん10歳だったの?」
海未「・・・適当です。さて、ここでアイドルフェス的なものが開催されることになり、出演者を出演順に配列に入れていくとしましょう。ところが・・・」
| 
					 1 2  | 
						var casts: SchoolIdol[] = [honoka, uzuki];  | 
					
海未「例えばこう書くと、コンパイルエラーになります。uzukiはSchoolIdolではないからですね」
ことり「じゃあ、var casts: ProfessionalIdol[] = [honoka, uzuki]もだめだよね」
穂乃果「だからってany[]にしちゃうと、フェスにアルパカが入り込んじゃうよね」
海未「そうです。この場合、以前見たようにSchoolIdolとProfessionalIdolが同じIdolクラスを継承している、といった構成になっていれば問題はないのですが、今回は別の方法をとりましょう」
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55  | 
						interface Singable {     sing(): void; } class SchoolIdol implements Singable {     constructor(         name: string,         age: number,         school: string     ) {}     sing() {         console.log('Singing!!');     }     dance() {         console.log('Dancing!!');     } } class ProfessionalIdol implements Singable {     constructor(         name: string,         age: number,         production: string     ) {}     sing() {         console.log('Singing!!');     }     talk() {         console.log('Talking!!')     } } class Alpaca {     constructor(         age: number     ) {}     bleat() {         console.log('meeeeeeeeeeeeeeee');     } } var honoka = new SchoolIdol('Honoka Kosaka', 16, 'Otonokizaka High'); var uzuki = new ProfessionalIdol('Uziki Shimamura', 17, '346Pro'); var alpaca = new Alpaca(10); var casts: Singable[] = [honoka, uzuki]; for (let cast of casts) {     cast.sing(); }  | 
					
海未「Singableというインターフェイスを用意して、SchoolIdolとProfessionalIdolはそれをimplementsすることにしましょう。こうすると、SchoolIdolとProfessionalIdolをどちらもSingable型として同じ扱いができるようになります」
穂乃果「歌える人だけ出場権があるんだ」
海未「Singableインターフェイスではsing(): voidという宣言がありますが、これはSingableインターフェイスを実装するクラスは必ずsingメソッドを持っていなくてはならないということです」
ことり「だからコードの最後で、キャスト全員のsingを呼び出したりできるんだね」
海未「この例では配列について見ましたが、同様に高階関数の引数宣言にも適用できます。また、クラスの継承関係に関係なく実装できますから、継承構造をまたがってグルーピングをしたい場合に便利ですね」
海未「最後に、これをインターフェイスなしに実現する方法を紹介します。構造的部分型という仕組みです」
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55  | 
						class SchoolIdol {     constructor(         name: string,         age: number,         school: string     ) {}     sing() {         console.log('Singing!!');     }     dance() {         console.log('Dancing!!');     } } class ProfessionalIdol {     constructor(         name: string,         age: number,         production: string     ) {}     sing() {         console.log('Singing!!');     }     dance() {         console.log('Dancing!!');     }     talk() {         console.log('Talking!!');     } } class Alpaca {     constructor(         age: number     ) {}     bleat() {         console.log('meeeeeeeeeeeeeeee');     } } var honoka = new SchoolIdol('Honoka Kosaka', 16, 'Otonokizaka High'); var uzuki = new ProfessionalIdol('Uziki Shimamura', 17, '346Pro'); var alpaca = new Alpaca(10); var casts: SchoolIdol[] = [honoka, uzuki]; for (let cast of casts) {     cast.sing(); }  | 
					
海未「ProfessionalIdolにdanceメソッドを追加しました。これによって、ProfessionalIdolはSchoolIdolと同じsingとdanceの各メソッドを持っていることになります」
穂乃果「ふむふむ」
海未「そうすると、SchoolIdol型が要求されるところに代わりにProfessionalIdolを渡すことができるようになります」
ことり「たしかに、SchoolIdolの配列に卯月ちゃん入れてるけど・・・どうしてなのかな」
海未「ProfessionalIdolはSchoolIdolと同じことができるから、ですね。singもdanceもできますから外から見た振る舞いは同じですし、実際JavaScriptでは同じことができました」
穂乃果「ダックタイピングだね」
ことり「ちゅんちゅん」
海未「次回はジェネリクスを紹介します。それで、TypeScriptの主な機能は一通りですね」