Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

TypeScript v4.1 で導入された機能のお話

この記事は「イエソド アウトプット筋 トレーニング 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に合わせられるよう設定する必要があるので注意。

image.png

あるいは、以下をプロジェクトルートに配置すればおkです。

.vscode/settings.json
{
  "typescript.tsdk": "node_modules/typescript/lib"
}

そうすれば、vscodeの右下のメニューから変更できるハズ。

スクリーンショット 2020-12-07 19.12.18.png

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}`; // 

こんな風に文字列リテラル内に別の型をバインドするようなことが出来ちゃいます。

image.png

これが便利だと言われてて、プレフィックスなりサフィックスなり何らか特定の文字を含んだ文字列を型としてバリデーションできたりしちゃいます。

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で型を定義できます。

image.png

ただ、現実的にチケット番号が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つ不足していたりプロトコルをタイポしたりというのが防げるようになります。

image.png

Notes

TypeScriptのrepositoryにもissueが挙がっている通り、
Template Stringsでバインドしている変数がたとえ厳密な型定義(non-widening)をされていても、その型情報は評価されず、string型として評価されます。

image.png

上記画像の例で言うと、


const domain = `google.com`; // type: "google.com"

なので、


const googleSearch = `https://${domain}/search`;

は、type: "https://google.com/search"と型評価されて欲しいところですが、実際にはstringとなります。


本当は他の機能についても書くつもりでしたが、既に30minを軽くオーバーしてしまっているため、一旦終わり。
時間と気力があれば続きを書きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?