あけましておめでとうございます。
ちょっと説明不足なところがあるので、追って追加します。
TypeScript 3.8 Beta
2020年1月10日にTypeScriptのver 3.8のBeta版が公開されました。少し前に3.7.2が公開されたような気がするので、けっこうはやいなあと思いました。Betaですからこんなものなのでしょうか。
いろいろ新しい機能が追加されたみたいなので簡単にまとめてみました。(自分がTypeScript初心者&&英語が苦手なので、間違いなどがあったら指摘してほしいです!)
インストール
NuGetを使う方法と、npmを使ってインストールする方法がありますが、自分はVSCodeを使ってTypeScriptを書いているのでnpmを使いました。
npm install typescript@beta
追加機能
結構多いのでざっと概要だけ書きます。
Type-Only Imports and Export
型のみをインポート、エクスポートすることができるようになります。
これを用いて、インポートする際などに型を明示的に扱うことができます。
構文は以下の通り
import type { SomeThing } from "./some-module.js";
export type { SomeThing };
注意点
これでインポートされるのは純粋に型の意味のみなので、値が使用されていてもその値は使用することができません。
import type { Hoge } from './foo';
let baseConstructor: typeof Hoge;
// ~~~~ Error!!
これに対してのフィードバックをうけて、この動作を変えることを検討しているようです。
まだ計画段階らしいですが、、import type
を使用してインポートされたものは、型でもそれ以外であっても常に型の位置でのみ許可されるように変える可能性もあると。なんにしても公式のアナウンスやアップデートを待ったほうがよさそうですね。
importsNotUsedAsValuesオプションの追加
使用されていないインポートがなされていた時の処理を制御するコンパイラフラグです。
設定できる値は以下の通り
-
remove(default)
現在の動作と同じ。使用されない要素はドロップされます -
preserve
使用されないインポートも保持されるようになります。 -
error
すべてのインポートが保持される点はpreserve
と同じですが、値のインポートが型として使用される場合、エラーとなります。
ECMAScriptプライベートフィールド
ECMAScript2015以降で使えるプライベートフィールドがサポートされました。
プライベートフィールドはクラス内でのみ参照可能なフィールドで、クラス外から参照しようとすると怒られます。
#hoge = 1
のように接頭辞に#
をつけることで宣言できます。
class Person {
#name: string
constructor(name: string) {
this.#name = name;
}
greet() {
console.log(`Hello, my name is ${this.#name}!`);
}
}
let jeremy = new Person("Jeremy Bearimy");
jeremy.#name // Error! クラス外部からの参照を許さない
privateとこの記述のどちらを使うべきかは状況によりそうです。
例えばECMAScript 2015(ES6)以上がターゲットでない場合、そもそもプライベートフィールド機能自体が使用できません。
export * as ns
Syntax
import * as ~
のような記述がexportでもできるようになりました。
export * as utilities from "./utilities.js";
Top-Level awaitのサポート
ECMAScriptの機能「Top-Level await」に対応しました。
await
を使用するにはasync
をつける必要がありましが、この「Top-Level await」を用いると、モジュールのトップであるときのみasyncがなくてもawaitを使うことができます。
const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);
// Make sure we're a module
export {};
※ moduleの設定をsystem
もしくはesnext
、targetの設定をes2017以上に設定してあげる必要があります。
JSDoc Property Modifiers
allowJsフラグをonにすることでjsファイルをサポート、かつchackJs,、もしくは@ts-checkコメントを先頭につけることで.jsファイルの型チェックもサポートします。
@public
, @private
, and @protected
修飾子があります。
// @ ts-check
class Foo {
constructor() {
/** @private */
this.stuff = 100;
}
printStuff() {
console.log(this.stuff);
}
}
new Foo().stuff; // Error!!
-
@public
プロパティに対してどこからでもアクセスできることを示します。省略可 -
@private
プロパティがクラス内からのみ使用できることを示します。 -
@protected
プロパティはクラス内と派生サブクラス内でのみ使用でき、宣言されてあクラスの異なるインスタンスでは使用できないことを示します。
また、初期化中にのみ書き込まれるようにする修飾子@readonly
も追加されました。
// @ts-check
class Foo {
constructor() {
/** @readonly */
this.stuff = 100;
}
writeToStuff() {
this.stuff = 200;
// ~~~~~
// Cannot assign to 'stuff' because it is a read-only property.
}
}
new Foo().stuff++; // Error!!
watchOption
ファイル監視のオプションが追加されました。
{
// いつもの
"compilerOptions": {
"target": "es2020",
"moduleResolution": "node",
// ...
},
// NEW: あたらしく追加された「watchOptions」
"watchOptions": {
//
"watchFile": "useFsEvents",
"watchDirectory": "useFsEvents",
// ファイルが頻繁に更新されるとき
"fallbackPolling": "dynamicPriority"
}
}
これには4つのオプションが含まれます。
- WatchFile
個々のファイルを監視する方法を設定します。- fixedPollingInterval
一定の間隔で毎秒数回、すべてのファイルの変更を確認します。 - priorityPollingInterval
すべてのファイルの変更を1秒間に数回チェックしますが、ヒューリスティックを用い、特定のタイプのファイルを他のファイルよりも頻繁にチェックしなくなります。 - dynamicPriorityPolling
変更頻度の少ないファイルのチェック頻度が低い動的キューを使用します。 - useFsEvents (default)
ファイルの変更にオペレーティングシステム/ファイルシステムのネイティブイベントを使用します。 - useFsEventsOnParentDirectory
オペレーティングシステム/ファイルシステムのネイティブイベントを使用して、ファイルを含むディレクトリの変更を検知します。これにより使用するファイルウォッチャーは少なくなりますが、制度が低下してしまう恐れがあります。
- fixedPollingInterval
- watchDirectory
再帰的なファイル監視機能がないシステムでディレクトリツリー全体を監視する方法を設定します。- fixedPollingInterval
すべてのディレクトリの変更を、一定の間隔で1秒間に数回確認します。 - dynamicPriorityPolling
変更頻度の低いディレクトリのチェック頻度が低い動的キューを使用します。 - useFsEvents (default)
ディレクトリの変更にオペレーティングシステム/ファイルシステムのネイティブイベントを使用します。
- fixedPollingInterval
- fallbackPolling
ファイルシステムイベントを使用する際、システムがネイティブファイルウォッチャーを使い果たしたり、サポートしていないときに使用するポーリングの設定を指定します。- fixedPollingInterval
- dynamicPriorityPolling
- useFsEvents (default)
- synchronousWatchDirectory
ディレクトリの遅延監視を無効にします。
assumeChangesOnlyAffectDirectDependenciesオプションの追加
長!!!
--incrementalモードに関連したコンパイルオプションです。
公式では*“Fast and Loose” Incremental Checking*「"高速で緩い"インクリメンタルチェック」と紹介されています。
assumeChangesOnlyAffectDirectDependenciesオプションを有効にすると影響を受ける可能性のあるすべてのファイルの再チェック/再構築を回避し、変更されたファイルと直接インポートするファイルのみを再チェック/再構築するようになります。
VSCodeのようなコードベースでは、このオプションによりファイル変更の再構築時間が14秒から1秒まで短縮されたようです。(自分でも検証してみます)
TypeScript3.8での変更
インデックスシグネチャを使用したユニオン型への厳密な割り当てチェック
以前は、存在しないキーに対してはコンパイルチェックが効かないようになっていました。
ver3.8では、プロパティがインデックスシグネチャを満たす場合のみ、プロパティチェックから除外します。
例えば以下のコードは従来であればエラーは起きませんでしたが、3.8ではエラーになります。
let obj1: { [x: string]: number } | { a: number };
obj1 = { a: 5, c: 'abc' } // cへの代入はインデックスシグネチャを満たさないためエラー
自分で触ってみて感じたことなど追記したり、情報が間違っていたら修正するので随時更新するつもりです。
またフィードバックを募集しているらしいので、触ってみた方は気になる点を報告するといいかもしれません。
参考