プログラミング言語「TypeScript 4.1」をMicrosoftが公開:新しい型を導入
Microsoftは、オープンソースのプログラミング言語の最新版「TypeScript 4.1」を公開した。さまざまな機能強化が施されており、パフォーマンスも向上している。
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.
関連記事
最も愛される言語は「Rust」――Stack Overflowが開発者調査結果を公開
開発者向けQ&Aサイト「Stack Overflow」が、2020年の年次開発者調査の結果を発表した。
Microsoft、プログラミング言語「TypeScript 4.0」を公開
Microsoftは、オープンソースのプログラミング言語の最新版「TypeScript 4.0」を公開した。多数の機能強化が行われ、パフォーマンスも向上している。
Microsoft、プログラミング言語「TypeScript 3.9」を公開
Microsoftは、オープンソースのプログラミング言語の最新版「TypeScript 3.9」を公開した。コンパイラの高速化やエディタ機能の強化、コーディング支援などの改良が行われている。
