プログラミング言語「TypeScript 4.1」をMicrosoftが公開新しい型を導入

Microsoftは、オープンソースのプログラミング言語の最新版「TypeScript 4.1」を公開した。さまざまな機能強化が施されており、パフォーマンスも向上している。

» 2020年12月17日 15時00分 公開
[@IT]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 Microsoftは2020年11月19日(米国時間)、オープンソースのプログラミング言語の最新版「TypeScript 4.1」を公開した。さまざまな新機能や新しいチェックフラグが導入され、エディタの生産性を高めるアップデートも施されており、速度も向上している。

 TypeScriptは静的型付けができる言語であり、JavaScriptのスーパーセットだ。ECMA規格に従った最新のJavaScriptの機能を、古いWebブラウザやランタイムが扱えるようにコンパイルすることもできる。

 TypeScript 4.1は、NuGetを使うか、次のコマンドラインのように、npmを使ってインストールできる。

npm install -D typescript

 TypeScript 4.1は「Visual Studio 2019」と「Visual Studio 2017」のエディタでサポートされており、「Visual Studio Code」(以下、VS Code)でも利用できる。TypeScript 4.1の主な特徴は次の通り。

テンプレートリテラル型を導入

 テンプレートリテラル型は、テンプレートリテラル表現と同等の型空間だ。テンプレートリテラル表現と同様に、テンプレートリテラル型はバックティックデリミタで閉じられ、「${T}」という形のプレースホルダーを含むことができる。「T」は、「string」や「number」「boolean」「bigint」に代入可能な型を指す。

 テンプレートリテラル型は、リテラル文字列を連結したり、非文字列プリミティブ型のリテラルを文字列表現へ変換したり、文字列の大文字小文字を変換したりできる。さらに、テンプレートリテラル型は型推論により、単純な形式の文字列パターンマッチングと文字列分解も可能だ。

 テンプレートリベラル型は、次のように変換される。

  • プレースホルダー内のユニオン型は、テンプレートリテラル型に分散される

 例えば、`[${A|B|C}]`は、`[${A}]` | `[${B}]` | `[${C}]`に変換される。複数のプレースホルダーに含まれるユニオン型は、クロス積に変換される。例えば、`[${A|B},${C|D}]`は、`[${A},${C}]` | `[${A},${D}]` | `[${B},${C}]` | `[${B},${D}]`に変換される。

  • プレースホルダー内のstring、number、boolean、bigintといったリテラル型は、プレースホルダーをリテラル型の文字列表現に置き換えられる

 例えば、`[${'abc'}]`は`[abc]`に変換され、`[${42}]`は`[42]`に変換される。

  • プレースホルダーに「any」「string」「number」「boolean」「bigint」といった型がある場合は、テンプレートリテラルをstring型に変換される
  • プレースホルダー内に「never」型がある場合は、テンプレートリテラルは「never」に変換される

 幾つかの例を次に示す。

type EventName<T extends string> = `${T}Changed`;
type Concat<S1 extends string, S2 extends string> = `${S1}${S2}`;
type ToString<T extends string | number | boolean | bigint> = `${T}`;
type T0 = EventName<'foo'>;  // 'fooChanged'
type T1 = EventName<'foo' | 'bar' | 'baz'>;  // 'fooChanged' | 'barChanged' | 'bazChanged'
type T2 = Concat<'Hello', 'World'>;  // 'HelloWorld'
type T3 = `${'top' | 'bottom'}-${'left' | 'right'}`;  // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
type T4 = ToString<'abc' | 42 | true | -1234n>;  // 'abc' | '42' | 'true' | '-1234'

マップ型におけるキーリマッピングに対応

 これまでマップ型は、開発者が提供したキーで新しいオブジェクト型を生成することしかできなかった。だが、入力に基づいて新しいキーを作成したり、キーを除去したりしたい場合も多い。

 そこでTypeScript 4.1では、新しい「as句」によって、マップ型のキーをリマッピングできるようになった。

type MappedTypeWithNewKeys<T> = {
    [K in keyof T as NewKeyType]: T[K]
    //
    //            This is the new syntax!
}

 この新しいas句により、テンプレートリテラル型のような機能を利用して、古いプロパティ名を基にプロパティ名を簡単に作成できるようになった。

type Getters<T> = {
    [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
interface Person {
    name: string;
    age: number;
    location: string;
}
type LazyPerson = Getters<Person>;

 また、neverを作成してキーを除去することも可能だ。つまり、場合によってはOmitヘルパー型を使わずに済む。

// Remove the 'kind' property
type RemoveKindField<T> = {
    [K in keyof T as Exclude<K, "kind">]: T[K]
};
interface Circle {
    kind: "circle";
    radius: number;
}
type KindlessCircle = RemoveKindField<Circle>;
// same as
//   type KindlessCircle = {
//       radius: number;
//   };

再帰的な条件型を作りやすくなった

 TypeScript 4.1では、条件型の一部の制限が緩和された。これにより、条件型が分岐内で自身を直接参照できるようになり、再帰的な型エイリアスを作成しやすくなった。

 例えば、ネストされた配列の要素型を取得する型を作成したい場合、次のようなdeepFlatten型を作成できる。

type ElementType<T> =
    T extends ReadonlyArray<infer U> ? ElementType<U> : T;
function deepFlatten<T extends readonly unknown[]>(x: T): ElementType<T>[] {
    throw "not implemented";
}
// All of these return the type 'number[]':
deepFlatten([1, 2, 3]);
deepFlatten([[1], [2, 3]]);
deepFlatten([[1], [[2]], [[[3]]]]);

 同様に、Promiseを深くアンラップするために、Awaited型を作成することも可能だ。

type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
/// Like `promise.then(...)`, but more accurate in types.
declare function customThen<T, U>(
    p: Promise<T>,
    onFulfilled: (value: Awaited<T>) => U
): Promise<Awaited<U>>;

インデックス付きアクセスのチェックを導入

 TypeScript 4.1では、「--noUncheckedIndexedAccess」という新しいフラグが導入された。この新しいモードでは、全てのプロパティアクセス(foo.barのような)やインデックス付きアクセス(foo["bar"]のような)が、潜在的に未定義と見なされる。

interface Options {
    path: string;
    permissions: number;
    // Extra properties are caught by this index signature.
    [propName: string]: string | number;
}
function checkOptions(opts: Options) {
    opts.path // string
    opts.permissions // number
    // These are all allowed too!
    // They have the type 'string | number'.
    opts.yadda.toString();
    opts["foo bar baz"].toString();
    opts[Math.random()].toString();
}

 上の例では「opts.yadda」が「string | number型」ではなく、「string | number | undefined型」を持つということだ。そのプロパティにアクセスする必要がある場合は、まずその存在をチェックするか、非nullアサーションオペレーター(後置の「!」)を使う必要がある。

// Checking if it's really there first.
if (opts.yadda) {
    console.log(opts.yadda.toString());
}
// Basically saying "trust me I know what I'm doing"
// with the '!' non-null assertion operator.
opts.yadda!.toString();

 --noUncheckedIndexedAccessを使った場合、配列へのインデックス付きアクセスが、境界チェックループでも、より厳密にチェックされる。

function screamLines(strs: string[]) {
    // this will have issues
    for (let i = 0; i < strs.length; i++) {
        console.log(strs[i].toUpperCase());
        //          ~~~~~~~
        // error! Object is possibly 'undefined'.
    }
}

 インデックスが不要な場合は、for-ofループやforEach呼び出しを使って、個々の要素を繰り返すことができる。

function screamLines(strs: string[]) {
    // this works fine
    for (const str of strs) {
        console.log(str.toUpperCase());
    }
    // this works fine
    strs.forEach(str => {
        console.log(str.toUpperCase());
    });
}

 このフラグは、境界外エラーを捉えるのに便利だが、多くのコードではノイジーかもしれない。そのため、--strictフラグでは自動的に有効化されない。

baseUrlなしのpathsが可能に

 パスマッピングを有効にするためにpathsを指定するには、baseUrlオプションも指定する必要があったが、baseUrlなしでpathsオプションを使えるようになった。

checkJsがallowJsを含意するように変更

 これまではcheckJsとともにallowJsを設定する必要があったが、checkJsがデフォルトでallowJsを含意するようになった。

React 17のJSXファクトリー関数に対応

 「react-jsx」と「react-jsxdev」とう新しいjsxコンパイラオプションにより、JavaScriptライブラリ「React 17」のjsxとjsxsファクトリー関数がサポートされた。これらのオプションはそれぞれ、本番用コンパイルと開発用コンパイルに対応している。

エディタにおけるJSDocの@seeタグのサポート

 TypeScriptとJavaScript用エディタにおけるJSDocの@seeタグのサポートが強化され、このタグに続くドット名で定義へのジャンプのような機能を利用できるようになった。

// @filename: first.ts
export class C { }
// @filename: main.ts
import * as first from './first';
/**
 * @see first.C
 */
function related() { }

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。