異なる型の配列の型を指定したい場合はtupleを使ったほうが良いかも
handbookやspecに書いてあることではあるけれど。
はじめに
例えば以下の様な定義があるとする。
class X { say() { return "x"; } } class Y { }
ここで以下のような型は型チェックを通らない。正しい。
let y: Y = new Y(); y.say();
もちろん以下のようなコードは正しい。
let x: X = new X(); y.say();
ここで異なる型の配列を指定したい場合がある*1。このような時はどうすれば良いかという話。
var values = [new X(), new Y()] values[0].say();
方法
any
一番単純なのはany型で定義して、利用する際にcastすることかもしれない。まぁ良くない。
// this is bad. let values: any[] = [new X(), new Y()]; console.log((<X>values[0]).say());
union type
次に考えるのはunion typeを使った配列の方として扱う方法。少なくとも、XかYのどちらかの型になることが保証される。 ただ、結局のところany[]型で定義するのと変わらない。
// this is not good let values: (X | Y)[] = [new X(), new Y()]; console.log((<X>values[0]).say());
tuple
こういう時はtupleを使うのが良さそう。tupleというのはusecaseそのもの。
let values: [X, Y] = [new X(), new Y()]; // 順序が異なればエラーになる // let values: [Y, X] = [new X(), new Y()]; // compile error console.log(values[0].say()); // もちろんYはsay()を持っていないのでエラーになる。 // console.log(values[1].say()); // compile error
memo: 可変長のtupleはissueにはなっているっぽい。
以下のようにも書きたいと言うことがあるかもしれない。可変長のtuple。これはissueにはなっているっぽい。
let values: [X, ...Y] = [new X(), new Y()];
参考
- https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Basic%20Types.md#tuple
- https://github.com/Microsoft/TypeScript/issues/1336
*1:例えば、angular.jsのdirectiveを定義した際のcontrollersの部分など