@kotyのブログ

PythonとかAWSとか勉強会のこととかを、田舎者SEがつづります。記事のライセンスは"CC BY"でお願いします。

TypeScript 0.8と0.9の間での破壊的変更

追記:@cocoa_ruto 様の指摘を受けて修正しました。ありがとうございます。勉強になります。訳しただけじゃなくて内容を理解しないと意味ないですね。。。

TypeScript0.9のalpha版が先日公開されました。このバージョンではかなり破壊的変更が入っています。それを調べるついでに、こちらのページを訳してみます。おかしな所があればご指摘ください。

読んでみると結構変わってますね。staticメソッドの呼び出しにクラス名の修飾が必須になったのが結構痛いです。

0.8と0.9の間の既知の破壊的変更 - Known breaking changes between 0.8 and 0.9

言語の成熟やECMAScript5および6、またコンパイラの仕様自身の一般的な準拠に資するために、0.9系は破壊的変更が入っている。われわれは、破壊的変更の数が少なくなるよう努めてはいるが、1.0に到達する前に必要な変更を行うことが重要である。*1

仕様に対するコンパイラの強化 - Tightening of compiler to spec

説明:仕様上厳密には許されていないが0.8.3コンパイラでは許されていた機能があった。例えば、protected をシミュレートするためのアクセス修飾子の利用など。

理由:われわれは、緩いコンパイラ実装に依存するのを避けるために、より厳密に仕様に忠実になるようコンパイラを強化した。

boolはbooleanになった。 - The type ‘bool’ is now ‘boolean’

説明:真理値の名前は、最初は'bool'だった。0.9.0の間は'bool'はdeprecatedとしてマークされ予定で、'boolean'をかわりに推奨する。0.9.1では'bool'は利用できなくなる予定だ。

理由:ECMAScriptにおける真理値型の名前は 'boolean'である。標準に合わせるために変更する。

'module'キーワードはもはや型を作らない - The ‘module’ keyword no longer creates a type

説明:0.9.0 において、名前空間、型、そして値の役割が明確に区別される。Moduleは名前空間と値のみを提供し、型は提供しない。

理由:Moduleの役割を簡素化することにより、モジュールがクラスと関数をより簡単に拡張できるようになる。

ジェネリック型の導入 - Array型の変更 - Introduction of generic types – Change to ‘Array’ type

説明:0.9.0 において、ジェネリック型の説明に関連するが、Array型はジェネリックとなった。

理由:以前は、Array型はより特別ではなかった。*2しかしジェネリックの降臨により配列内の型をより明確にできる。

ジェネリック型の導入 - 構文解釈の変更 - Introduction of generic types – Change to syntax parsing

説明:0.9.0 において、ジェネリック型の説明に関連するが、構文解釈の方法の違いが説明された。これは、ES5で許容されると以前は解釈されていた構文のいくつかのformsに影響を与える可能性がある。特に次の例は、two comparisonsのカンマ区切り式としてはもはや解釈されず、かわりに2つの引数をとるジェネリック関数の呼び出しとして解釈される。

myfun<x,y>(z)

このあいまいさを回避するために括弧を使うこと。例えば下記。

(myfun < x), y > (z)

理由:われわれは、ジェネリック構文に関してほかの言語によって位置づけられる優位性を追従する。残念ながら、このことはいくつかのケースであいまいさをもたらす。

オーバーロード宣言は実装のすぐ前に書かなければならない - Overload declarations must immediately precede implementation

説明:0.8系はオーバーロード宣言とその実装に関して何が許されるかが、緩かった。

追記)foo(a:string); foo(a:number); foo(a:any) {...}のように書くようになったという意味とのこと。@cocoa_ruto 様より。

理由:文法に合わせるためにコンパイラを強化する

インデクサは型を完全に明示しなければならない - Indexers must have full type annotation now

説明:

interface a1 {
    [n: number];  //<-- was allowed in 0.8.x, now an error
}
interface a1 {
    [n: number]: string;  //<-- correctly specifies return type, valid in 0.8.x and 0.9.x
}

理由:文法に合わせるためにコンパイラを強化する。

静的メンバは完全に修飾されなければならない - Statics must be fully-qualified

説明:静的メンバ宣言の中では、以前は完全に修飾しないことができた。

理由:単純にクラスは"this."を必要とするので*3、そのシンボルがどこに由来しているか示すために静的メンバはクラス名を必要とする。

メソッドの最後にセミコロンを付けるのはもはや許容しない - No longer accept semicolon at the end of methods

説明:

class Todo extends Backbone.Model {
 
    // Default attributes for the todo.
    defaults() {
        return {
            content: "empty todo...",
            done: false
        }
    };
}

理由:0.9.0の忠実な(fidelity)パーサにおいて構文により厳密に追従することに由来しているかもしれない。われわれは、将来この制限を緩くするかもしれない。

"new number[]" はもはや許容しない - No longer accept "new number[]"

説明:0.8系において、newの後には式が続くべきというルールに対するいくつかの例外をわれわれは許した。ここで、newに続くものとして"number[]"という型をわれわれは許していた。

理由:0.8系のコンパイラにおいて意図せずに許されたものだ。0.9系の作業の一部として、われわれはコンパイラを強化し、そのようにするのをもはや許さない。

.d.tsファイルにおいて、interfaceでない型の宣言にdeclareが必須 - 'declare' now required for top level non-interface declarations in .d.ts files

説明:0.8系は.d.tsファイルにおいて多くの緩さを持っていた。われわれは構文を強化したい。

理由:緩い構文ルールはユーザーを混乱させており、.d.tsファイルに非一貫性をもたらしている。

文字列インデクサはインターフェースにおいてメンバーの型に制約を課す - String indexers constrain the types of members on the interface

説明:element型のFooが付随した文字列インデクサは、interfaceの全てのメンバがFooに対して互換性のある型を持つという制約である。唯一の例外は、いかなるobject型においても呼び出されるObjectを暗黙的に継承したメンバーが、明示的にオーバーライドされない限りObjectにおいて提供される型を持ちつづけることだ。したがってこれは、

   export interface IEventListenerMap {
        hasOwnProperty(eventName: string): bool;
        [eventName: string]: IEventCallback[];
    }

interfaceの利用者に変更がないようにするために、このように変更される。(すなわち、彼らは.hasOwnPropertyを使い続けることができる)

    export interface IEventListenerMap {
        [eventName: string]: IEventCallback[];
    }

理由:0.9において、文字列インデクサはプロパティのルックアップに統合された。したがって、foo.bar と foo["bar"]は同じく振る舞う。

*1:とTypeScriptチーム考えたってことか??

*2:型無しってことか?

*3:Just as classes require “this.”