オブジェクトの形を書く

INPUT · スライド

形が同じなら通る

01 / 06

見ているのは名前ではなく形

interface で形に名前をつけてきたけれど、TypeScript が見ているのは名前ではなく中身の形だよ。

Hito を受け取る関数に、Hito と名乗っていないただのオブジェクトを渡してみよう。必要なプロパティがそろっていれば、そのまま通る。

interface Hito {  namae: string;}function yobu(h: Hito): void {  console.log(h.namae + "さん");}const x = { namae: "ゆい" };yobu(x);

実行結果

ゆいさん

02 / 06

別々に宣言した同じ形も入れかわる

名前のちがう2つの型でも、中身の形が同じなら入れかえられる。

型の名前は人間が読むための呼び名でしかなくて、合うかどうかの判断はぜんぶ形でやっているんだ。この決め方を構造的な型づけと呼ぶよ。

interface Hito {  namae: string;}interface Kyaku {  namae: string;}const k: Kyaku = { namae: "りん" };const h: Hito = k;console.log(h.namae);

実行結果

りん

03 / 06

足りないと通らない

形で見るといっても、ゆるいわけではないよ。そろっていないものは通らない

toshi を持たないオブジェクトを Hito の引数に渡すと、渡したその行で止まる。エラーは「どのプロパティが足りないのか」まで言ってくれるから、そのまま読めばいい。

interface Hito {  namae: string;  toshi: number;}function yobu(h: Hito): void {  console.log(h.namae);}const x = { namae: "ゆい" };yobu(x);

実行結果

型のエラー: 型 '{ namae: string; }' の引数を型 'Hito' のパラメーターに割り当てることはできません。
  プロパティ 'toshi' は型 '{ namae: string; }' にありませんが、型 'Hito' では必須です。

04 / 06

余分に持っていても通る

足りないとだめだけれど、多いぶんには困らない

toshiHito に無いプロパティだ。それでも namae がそろっているから、yobu の中でやりたいことはちゃんとできるよね。だから通す。

interface Hito {  namae: string;}function yobu(h: Hito): void {  console.log(h.namae);}const x = {  namae: "ゆい",  toshi: 20,};yobu(x);

実行結果

ゆい

05 / 06

ところが、その場で書くと止まる

同じ中身なのに、書き方を変えると結果が変わる。変数に入れてから渡したときは通ったものが、かっこの中に直接書くと止められるんだ。

意地悪をされているように見えるけれど、ちゃんと理由があるよ。

interface Hito {  namae: string;}function yobu(h: Hito): void {  console.log(h.namae);}yobu({ namae: "ゆい", toshi: 20 });

実行結果

型のエラー: オブジェクト リテラルは既知のプロパティのみ指定できます。'toshi' は型 'Hito' に存在しません。

06 / 06

なぜ書き方で結果が変わるの?

理由はこうだよ。その場で書いたオブジェクトは、そこ以外で使いようがないtoshi20 を書いたのに Hito が受け取らないなら、その 20 はどこにも届かない。書いた本人は届くつもりでいるはずだから、たぶん打ちまちがえだ — そう考えて止めてくれる。これを余剰プロパティチェックと呼ぶよ。

変数に入れた場合はちがう。その変数は別のところでも使われるかもしれないから、余分を持っていても不自然じゃない。だから通す。

合わせるのは形、ただしその場で書いたものだけは厳しく見る。ここから書いてみよう。