TypeScriptで型にもスプレッド構文使えるよ~って話
手っ取り早く、使い方を見たい方はこちらへジャンプ
スプレッド構文について
みなさん、JavaScriptのスプレッド構文を使っているだろうか?
まだ詳しくは知らないよという方は、まずこちらを見るとよい。
具体的なスプレッド構文の使い方
自分はオブジェクト型を扱うときは頻繁に使う構文である。具体的な例として、フロントエンドでの無限スクロールの実装が挙げられる。その際、既にあるデータと新しく取ってきたデータの結合にスプレッド構文を使う。
const prevData = [ /* 元からあるデータ */
{
id: 'article-id-1',
title: '記事のタイトル',
content: '....'
},
....
];
const newData = [ /* 新しいデータ */
{
id: 'article-id-1',
title: '記事のタイトル',
content: '....'
},
....
]
const data = [...prevData, ...newData]; /* 合体! */
イメージとしては...
を付けることによって、配列の[]
を外して取り扱う感じ。スプレッドつまり展開しているのだ。新しいデータ分、For文を回してArray.push()
を行うより断然良い。
型においてのスプレッド構文とは
展開という意味は同じである。つまり型を展開すると言ってもいいかも(?) ユースケースとしては、配列が挙げられる。1つ目と2つ目以降が異なる配列の型はどのように書けばよいのだろうか。1つの案として、ユニオンタイプを用いた
type SpecificArray = (string|number)[];
もあるだろう。これでも今回実現したい型に近いづいた。これであれば1つ目や2つ目以降関係せず、string
またはnumber
型を格納できる。しかし、その値を使う際、タイプガードによって型を確定させる必要がある。また型が複雑になればなるほど、タイプガードも複雑となる。
くわえて、1つ目の型が確定しているのにも関わらず、オプショナルタイプを使うことに疑問を持ってしまう。
type StupidType = [string, number, number];
これは論外である。型によって、要素の数を決めてしまい汎用性がまったくない。
そこでのスプレッド構文である。
具体的な型においてのスプレッド構文の使い方
type ArrayType = [string, ...Array<number>];
Array
はPartial
[1]などのAdvanced Type
の1つである。Array<number>
でnumber[]
を同等の型を表す。そのため、
type ArrayType = [string, ...number[]];
という書き方でも良い。このようにして、1つ目はstring
型、2つ目以降はnumber
型という配列の型を定義できた。
勘違いしやすそうな表現
type ObjectType = ObjectType1 & ObjectType2;
これによってObjectType
ではObjectType1
とObjectType2
の型が使える。それに従って、
type ArrayType = [string] & number[];
これで1つ目にはstring
型、2つ目以降はnumber
型とはならない。ここでのArrayType
は1つの要素数でstring
型と定義される。
TypeScriptは奥深いなと改めて思ったのであった。
-
Partial
はジェネリクスの引数にオブジェクト型を入れることによって、すべてのキーをオプショナルタイプにするというAdvanced Type
である。 ↩︎
Discussion
型にspread演算子が使えると知らず大変助かりました。
1点確認なのですが、
string|number
という表現はOptionalというよりはUnionかなと思ったのですがどうでしょう?確かにUnionが正しいですね。修正しておきます!
ご指摘ありがとうございます🙇