LoginSignup
33
13

More than 3 years have passed since last update.

TypeScript 3.8 Beta 追加機能等まとめ

Last updated at Posted at 2020-01-13

あけましておめでとうございます。

ちょっと説明不足なところがあるので、追って追加します。

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
      オペレーティングシステム/ファイルシステムのネイティブイベントを使用して、ファイルを含むディレクトリの変更を検知します。これにより使用するファイルウォッチャーは少なくなりますが、制度が低下してしまう恐れがあります。
  • watchDirectory 再帰的なファイル監視機能がないシステムでディレクトリツリー全体を監視する方法を設定します。
    • fixedPollingInterval
      すべてのディレクトリの変更を、一定の間隔で1秒間に数回確認します。
    • dynamicPriorityPolling
      変更頻度の低いディレクトリのチェック頻度が低い動的キューを使用します。
    • useFsEvents (default) ディレクトリの変更にオペレーティングシステム/ファイルシステムのネイティブイベントを使用します。
  • 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への代入はインデックスシグネチャを満たさないためエラー

自分で触ってみて感じたことなど追記したり、情報が間違っていたら修正するので随時更新するつもりです。

またフィードバックを募集しているらしいので、触ってみた方は気になる点を報告するといいかもしれません。

参考

33
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
13