TypeScriptのスプレッド構文に気を付けて

に公開

はじめに

TypeScriptにはスプレッド構文という便利な記法があります。その記法を使えば、オブジェクトからオブジェクトへの値の代入が簡単になりますが、注意点があったので記事を書きたいと思います。

記事で紹介しているコードはTypeScript Playgroundで試すことが出来ます。

スプレッド構文の説明

オブジェクトでの使い方

説明

スプレッド構文とは、下のコードの...{変数名}としている記法のことです。
この記法を用いることで、UserからUserResのオブジェクトに値を入れなおすことが出来ます。

type User = { id: number; name: string; }
const user = { id: 0, name: "あお"}

type UserRes = { id: number; name: string; }
const resUser: UserRes = { ...user }

console.log(resUser)

出力

{
  "id": 0,
  "name": "あお"
} 

便利な使い方

スプレッド構文を使いながら、ageのような足りないメンバを補ったり、
nameのように上書きすることが出来ます👍
足りないメンバがある場合は、TypeScriptが指摘してくれるので安心です💕

type User = { id: number; name: string; }
const user = { id: 0, name: "あお"}

type UserRes = { id: number; name: string; age: number}
const resUser: UserRes = { ...user, name: "ウグイス", age: 26 }

console.log(resUser)

出力

 {
  "id": 0,
  "name": "ウグイス",
  "age": 26
} 

使い方3

複数のスプレッド構文を使うこともできます。

type User = { id: number; name: string; }
const user = { id: 0, name: "あお"}

const userAddress = { pref: "神奈川", city: "横浜"}

type UserRes = { id: number; name: string; age: number; pref: string, city: string}
const resUser: UserRes = { ...user, name: "ウグイス", age: 26, ...userAddress}

console.log(resUser)

配列での使い方

配列を結合することが出来ます。

const list1 = [0, 1, 2]
const list2 = [3, 4, 5]

const listNew = [...list1, ...list2]

console.log(listNew)

出力

[0, 1, 2, 3, 4, 5] 

スプレッド構文の注意点

一番伝えたいことになります。

以下のようにスプレッド構文を書いた場合resUserはどうなるでしょうか?
TypeScriptで型注釈しているから、userResには{ id: 0, name: "あお"}が入るはず。
メンバが足りなかったら怒られるし。。

type User = { id: number; name: string; innerData: string }
const user = { id: 0, name: "あお", innerData: "外に出す必要がないデータ"}

type UserRes = { id: number; name: string; }
const resUser: UserRes = { ...user }

console.log(resUser)

しかし、出力されるのは以下の内容になります。

{
  "id": 0,
  "name": "あお",
  "innerData": "外に出す必要がないデータ"
} 

UserResの型にはないinnerDataが入ってしまいます😰

これに関しては、こういう仕様だとしか言えないのですが、
スプレッド構文は下のようにJavaScriptに変換されます。

const resUser = Object.assign({}, user);

TypeSciptはメンバが足りないときに指摘してくれたとしても、
余分なメンバがある時には指摘せずにObject.assign({},...)に変換してしまいます。
このコードが動けば余分メンバが入ってしまいます😢

これを回避するためには、メンバごとに代入をしていく必要があります。

おわりに

スプレッド構文はコードが少なくなって、見やすくはなりますが、
代入先の型注釈に無いメンバが入りこむ場合がありますの、使い場所に注意しましょう!

コラボスタイル Developers

Discussion