Apr 9, 2022
7 mins read
今回もmattoさんのコードリーディングをしていく。
TypeScript Tip #3
今回はTypeScriptのユーティリティをまとめたライブラリts-toolbelt
について説明していく。
注意点としては、TypeScriptバージョンが4.1以上である必要がある。
数多くのユーティリティが提供されているため、今回はMattさんの解説に絞ってまとめていく。
ts-toolbelt
ライブラリの中から使用したいユーティリティをimportして使用する。
import { String, Union } from 'ts-toolbelt';
今回はURLの操作をする時に便利なユーティリティをまとめていく。
import { String, Union } from 'ts-toolbelt';
const query = '/home?a=foo&b=wow'
type Query = typeof query
// type Query = "/home?a=foo&b=wow"
type SecondQueryPart = String.Split<Query, '?'>[1]
// type SecondQueryPart = "a=foo&b=wow"
type QueryElements = String.Split<SecondQueryPart, '&'>
// type QueryElements = ["a=foo", "b=wow"]
type QueryParams = {
[ QueryElement in QueryElements[number] ]: {
[ key in String.Split<QueryElement, '='>[0]]: String.Split<QueryElement, '='>[1]
}
}[QueryElements[number]]
// type QueryParams = {
// a: "foo";
// } | {
// b: "wow";
// }
const obj: Union.Merge<QueryParams> = {
a: 'foo',
b: 'wow'
}
// const obj: {
// a: "foo";
// b: "wow";
// }
type SecondQueryPart = String.Split<Query, "?">;
でリテラル型を?
で区切りタプル型を作成する。
よって、type SecondQueryPart = ["/home", "a=foo&b=wow"]
になる。その後、ルックアップ型で要素を取得している。
type SecondQueryPart = String.Split<Query, '?'>[1]
でtype SecondQueryPart = "a=foo&b=wow"
の型を取得することができる。
TypeScript のルックアップ型と keyof キーワード
type QueryElements = String.Split<SecondQueryPart, "&">;
は上記と同じように&
で区切りタプル型を作成している。
そのため、type QueryElements = ["a=foo", "b=wow"]
になる。
QueryParams
型のインデックスシグネチャをみていく。
QueryElement in QueryElements[number]
のQueryElements[number]
は、以下の様になる。
QueryElements[number]
🔽
["a=foo", "b=wow"][number]
🔽
"a=foo" | "b=wow"
よって、QueryElement in QueryElements[number]
はQueryElement in "a=foo" | "b=wow"
でマップ型が作成される。
4. Key in String.Split<QueryElement, "=">[0]
のString.Split<QueryElement, "=">[0]
は以下になる。
a=foo
の場合
String.Split<'a=foo', "=">[0]
🔽
"a"
上記と同じ様にString.Split<QueryElement,"=">[1]
も時も以下の様になる。
String.Split<QueryElement,"=">[1]
🔽
"foo"
type QueryParams = {
[QueryElement in QueryElements[number]]: {
[Key in String.Split<QueryElement, "=">[0]]: String.Split<QueryElement,"=">[1];
};
}
🔽
type QueryParams = {
"a=foo": {
a: "foo";
};
"b=wow": {
b: "wow";
};
}
type QueryParams = {
[QueryElement in QueryElements[number]]: {
[Key in String.Split<QueryElement, "=">[0]]: String.Split<QueryElement,"=">[1];
};
}[QueryElements[number]];
🔽
type QueryParams = {
"a=foo": {
a: "foo";
};
"b=wow": {
b: "wow";
};
}["a=foo" | "b=wow"];
🔽
type QueryParams = {
a: "foo";
} | {
b: "wow";
}
Union.Merge<T>
でユニオン型の型をインターセクション型に定義することができる。Union.Merge<QueryParams>
🔽
Union.Merge<
{
a: "foo";
} | {
b: "wow";
}>
🔽
{
a: "foo";
b: "wow";
}
ts-toolbeltの存在を初めて知ったので、非常に勉強になった。比較的バージョンを新しくする必要があるので、 使用できる環境があれば、積極的に公式のドキュメントを参考にしていきたい。
TypeScript Tip #3
ts-toolbelt
TypeScript のルックアップ型と keyof キーワード