VSCodeでJavascriptを使うときの型推論の話です。
ほとんど箇条書きですが、簡単なサンプルを併記しているので それほど難しくはないかと思います。
関数で使える
関数を実行するときに実際に渡した引数の型をベースにして型を推測してくれるようになります。
templateの記述が無いときは、any型になります。
/**
* @template T
* @param {T} value
*/
function foo (value) {
return value;
}
let a = foo(1); // number
let b = foo(''); // string
クラスでも使える
関数だけではなく、クラスでも使えます。
/**
* @template T
*/
class Bar {
/**
* @param {T} value
*/
constructor (value) {
this.value = value;
}
baz () {
return this.value;
}
}
let bar = new Bar(0);
let foo = bar.baz(); // number
型注釈をつけるときは<>で指定できます。
/** @type {Bar<number>} */
let bar = new Bar(0);
Javascript標準の Array や Set はこれに該当します。
例: Array<string>
, Set<number>
2つ以上宣言できる
Javascript標準の Object や Map はこのパターンです。
例: Object<string, any>
, Map<number, boolean>
/**
* @template T
* @template U
*/
class Dictionary {
/**
* @param {T} key
* @param {U} value
*/
set (key, value) {}
}
/** @type {Dictionary<string, number>} */
let dic = new Dictionary();
dic.set('width', 100);
ベースとなる型を指定できる
template と T の間に型注釈を入れれば、型を限定することができます。
/**
* @template {string} T
* @param {T} value
*/
function hoge (value) {
return value;
}
let valA = '';
let hogeA = hoge(valA); // string
let valB = 0;
let hogeB = hoge(valB); // これは警告される
// ベースよりも限定的な型は問題なく使える
/** @type {'A' | 'B'} */
let valC;
let hogeC = hoge(valC); // "A" | "B"
発展的な使い方
その1 返り値の型補完
/**
* @template T
* @template U
*/
class Dictionary {
/**
* @returns {Array<T>}
*/
keys () { return []; }
/**
* @returns {Array<U>}
*/
values () { return []; }
}
/** @type {Dictionary<string, number>} */
let dic = new Dictionary();
let keys = dic.keys(); // string[]
let values = dic.values(); // number[]
その2 keyofとの併用
引数のプロパティをkeyofで抽出しています。
/**
* @template {Object<string, any>} T
*/
class ValueReader {
/**
* @param {T} obj
*/
constructor (obj) {
this.obj = obj;
}
/**
* @param {keyof T} key
*/
read (key) {
return this.obj[key];
}
}
let reader = new ValueReader({ id: '01', name: 'white' });
// readの引数が "id" | "name" になる
let id = reader.read('id');
雑感など
keyof や extends と組み合わせれば、インテリセンスをよりリッチにすることができます。
使いどころは探せばあるので、試してみてください。