28
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TypeScript 2.9 変更点

Last updated at Posted at 2018-06-01

こんにちは。LINEの@uta_ttiです。

今日TypeScript 2.9がリリースされました。2.8のconditional typesと比べるとちょっと破壊力が足りない気もしますが、個人的に待っていた機能が入ったりしたので、紹介したいと思います。今回のアップデートではCLIやツール系の改善も多かったですが、言語自体の変更点だけ紹介します。詳しくは公式記事を参考してください。

もし内容(や日本語)などが間違ってたら教えてください。

import(...)式からの型import

import(...)はES modulesを動的に読み込む式になります。「式」という単語を使っていますが、実際import(...)は関数ではなく文法要素です。なのでtypeof importしても結果は出ませんし、第一級として扱うことも出来ません。

import(...)は現在ES仕様のステージ3であり、もうChromeなどでは実装されています。

TypeScriptでももちろんimport(...)自体は使えましたが、import(...)から型はimport出来なかったため、不自然にtop-level importを混ぜて使うしかありませんでした。

import { SomeType } from "./foo"

async function func() {
  let val: SomeType

  // ...

  val = (await import("./foo")).someValue
}

TypeScript 2.9 ではimport(...)が型情報も提供してくれるので、以下のように書けます。

async function main() {
  let val: import("./foo").SomeType

  // ...

  val = (await import("./foo")).someValue
}

JSON import

今まではJSONファイルはrequire(...)を使ってimportするしかなく、型はいつもanyでした。

let pkg = require("./package.json") // any
pkg.name // any

TypeScript 2.9からはJSONファイルにもimportを使えるようになり、型もつけてくれます。

import pkg from "./package.json"
pkg.name // string

keyof型の変更

今までkeyofは文字列ベースのキーにしか対応しませんでした。

interface X {
  str: any,
  1: any,
  [symbol]: any
}

keyof X // "str" | "1"

keyof any[] // "map" | "length" | ...

TypeScript 2.9からはnumberSymbolなどのキーにも対応し、Arrayの場合ちゃんとnumberもキーに含めてくれます。

interface X {
  str: any,
  1: any,
  [symbol]: any
}

keyof X // "str" | 1 | symbol

keyof any[] // number | "map" | "length" | ...

上の変更で、例えばkeyof Xの型の変数に"1"を入れるとエラーになります。破壊的な変更なので、対応が必要な場合があります。もし今までstringをとあるオブジェクトのキーの型として使ってたとしたら、stringの代わりに以下のように型を宣言して使うとよいです。

type ObjectKey = keyof any // instead of `string`

もしTypeScript 2.8までのように文字列ベースの動作が欲しい場合、compilerOptionskeyofStringsOnlyが新しく追加されましたので、これをtrueにすると以前と同じ動作でコンパイルしてくれます。

Tagged template literalsの型変数サポート

Tagged template literalsとは以下のようにとある関数をtemplate literalのtagとして使うものです。

func`hello${x}world${y}yay`;

上の式は実際以下のように書くのと同じです。

func(["hello", "world", "yay"], x, y);

Tagged template literalsについて詳しくは下のMDN文書を参考してください。

上の例で確認できるよう、tagged templateのtagは普通の関数です。TypeScriptでは関数に型変数を提供してpolymorphicな動作をさせることが出来ます。

function func<X, Y>(strs: TemplateStringsArray, x: X, y: Y)

func<string, number>([...], "hello", 10);

しかしtagged templateの場合それが出来ませんでした。

func<string, number>`hello${x}world${y}yay`; // syntax error
func`hello${x}world${y}yay`; // x: any, y: any

TypeScript 2.9では、tagged templateでも型変数を使えるようになりました。

func<string, number>`hello${x}world${y}yay`; // x: string, y: number

この機能を一番まっていたのはstyled-componentsではないかと思います。styled-componentsはcomponent定義でcustom propsも使えるようにしていますが、TypeScriptではcustom propsの型を提供することが出来ませんでした。

const MyH1 = styled.h1`
  color: ${props => props.customProp}
`; // type error, no `customProp` in props

それをTypeScript 2.9では以下のように提供できるようになります。

type MyH1Props = { customProp: string };

const MyH1 = styled.h1<MyH1Props>`
  color: ${props => props.customProp}
`;

実は上のコードはstyled-componentsに型バグがあるためまだ動きません。その修正をpull requestで出しておきました。

その他

その他、マイナーな変更点が何個かありますので、気になる方は公式記事を見てみてください。

28
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
28
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?