この記事は「イエソド アウトプット筋 トレーニング Advent Calendar 2020」7日目の記事です。
短時間でさっと書いて、アウトプット力を少しでも高めることが目標なので、最近リリースされたTypeScriptの新バージョンについてさっと書いてみます。
TypeScript Version
本記事の内容は、2020年11月にリリースされたTypeScript4.1.2の新機能についてです。
$ npm search typescript
NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS
typescript | TypeScript is a… | =typescript-de… | 2020-11-19 | 4.1.2 | TypeScript Microsoft compiler language javascript
ローカルで実際に確認したい場合は、
$ mkdir ts-4.1 && cd $_
$ npm init -y
$ npm i -D typescript
$ npx tsc --init
$ tree -L 2
.
├── node_modules
│ └── typescript
├── package-lock.json
├── package.json
└── tsconfig.json
で必要最低限の環境で確認できます。終わったらディレクトリ削除しちゃいましょう。(各種binがある前提)
vscodeで確認する場合は、vscodeが使用するTypeScriptのversionをprojectでインストールされたTypeScirptに合わせられるよう設定する必要があるので注意。
あるいは、以下をプロジェクトルートに配置すればおkです。
{
"typescript.tsdk": "node_modules/typescript/lib"
}
そうすれば、vscodeの右下のメニューから変更できるハズ。
Template Literal Types
段階を踏んで説明するため、先に以下2つをご紹介。
(String) Literal Types
TypeScirptでは、文字列リテラルを(文字列に問わず 数値/真偽値/オブジェクト でも)型として使用することができます。
type Status = 'success' | 'error';
const status1: Status = 'success';
let status2: Status = 'success';
status2 = 'error';
const errStatus: Status = 'warn'; // error
Template Strings
通常の文字列リテラルの記述は'
(シングルクォーテーション)または"
(ダブルクォーテーション)で書くことが多いと思います。
一方で、文字列内に変数をバインドしたい場合や、複数行に渡る文字列を宣言したい場合、バッククォーテーションで書くと非常にシンプルになります。
function hello(name: string) {
console.log(`Hello, ${name}`);
}
const name = 'swallowtail62';
hello(name); // `Hello, swallowtail62`という文字列がコンソール出力される
Template Literal Typesは上記の2つの機能を組み合わせたようなものだとイメージしてもらえば分かりやすい?と個人的に思っています。
type Status = `Success` | `Error`; // テンプレート文字列リテラルでの型定義は、v4.1以前からOK (Qiita上ではこのsyntax errorに見えちゃうけど)
type Result = `status: ${Status}`; //
こんな風に文字列リテラル内に別の型をバインドするようなことが出来ちゃいます。
これが便利だと言われてて、プレフィックスなりサフィックスなり何らか特定の文字を含んだ文字列を型としてバリデーションできたりしちゃいます。
type Prefix = `YSD-`;
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type TicketId = `${Prefix}${Digit}`;
const ticketId: TicketId = 'YSD-0'
番号が1桁の場合には、上記のTicketId
で型を定義できます。
ただ、現実的にチケット番号が1桁で収まるハズはなく、正規表現のように
type TicketId = `${Prefix}${Digit}+`;
みたいな感じで定義できればいいんですが、やり方があるのかは分かりません。。
もっと身近に扱えて恩恵を受けられるとすれば、url定義とかでしょうか。
type Url = `${'http' | 'https'}://${string}`;
const min: Url = 'http://';
const normal: Url = 'https://qiita.com';
const abnormal1: Url = 'http:/qiita.com';
const abnormal2: Url = 'htpps://qiita.com';
/
が1つ不足していたりプロトコルをタイポしたりというのが防げるようになります。
Notes
TypeScriptのrepositoryにもissueが挙がっている通り、
Template Stringsでバインドしている変数がたとえ厳密な型定義(non-widening)をされていても、その型情報は評価されず、string
型として評価されます。
上記画像の例で言うと、
const domain = `google.com`; // type: "google.com"
なので、
const googleSearch = `https://${domain}/search`;
は、type: "https://google.com/search"
と型評価されて欲しいところですが、実際にはstring
となります。
本当は他の機能についても書くつもりでしたが、既に30minを軽くオーバーしてしまっているため、一旦終わり。
時間と気力があれば続きを書きます。