microsoft / microsoft/TypeScript
Idea: 'rest' index signatures and the 'error' type
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
[This idea is still in a relatively early stage of development, but I thought it may be of worth to someone or even for the TS team itself. Feel free to share your thoughts]
Having literal types, or unions of them, in index signatures is an idea that was brought to discussion lately (see #5683, #7656 and more general discussion in #7660):
interface Example {
[letter: "a" | "b" | "c"]: number;
}
However the conventional semantics of index signatures would imply that the type checking here would be very weak, unless noImplicitAny is enabled:
let x: Example;
x["a"] = 123; // OK
x["a"] = "ABCD"; // Error: type 'string' cannot be assigned to 'number'
x["d"] = 123; // No error with noImplicitAny disabled
x["d"] = "ABCD"; // No error with noImplicitAny disabled
x[123] = "ABCD"; // No error with noImplicitAny disabled
x[Symbol("ABCD")] = true; // No error with noImplicitAny disabled
let y = x["a"] // OK, 'y' gets type 'number'
let y = x["d"] // No error with noImplicitAny disabled, 'y' gets type 'any'
let y = x[123] // No error with noImplicitAny disabled, 'y' gets type 'any'
let y = x[Symbol("ABCD")] // No error with noImplicitAny disabled, 'y' gets type 'any'
What if it there was a way to specify the type of all the 'remaining' access keys to the interface with a special "rest" index signature (notated as [key: ...any]: T) that would set a particular type for everything other than that was specified in the interface?
interface Example {
[letter: "a" | "b" | "c"]: number;
[otherKeys: ...any]: string;
}
This may also be useful to avoid unwanted type errors when noImplicitAny is enabled:
interface Example {
[letter: "a" | "b" | "c"]: number;
[otherKeys: ...any]: any;
}
And what if it would be set to some sort of an 'error' type? I.e. a type that would not be assignable to or from anything? (perhaps except itself, still thinking about it..).
interface Example {
[letter: "a" | "b" | "c"]: number;
[otherKeys: ...any]: <Error>;
}
With the <Error> type, any assignment to or from a key that is not "a", "b" or "c" would yield an error, as it cannot be assigned to or from anything:
let x: Example;
x["a"] = 123; // OK
x["a"] = "ABCD"; // Error: type 'string' is not assignable to 'number'
x["d"] = 123; // Error: type 'number' is not assignable to '<Error>'
x["d"] = "ABCD"; // Error: type 'string' is not assignable to '<Error>'
x[123] = "ABCD"; // Error: type 'string' is not assignable to '<Error>'
x[Symbol("ABCD")] = true; // Error: type 'boolean' is not assignable to '<Error>'
let y = x["a"] // OK, 'y' gets type 'number'
let y = x["d"] // Error: type '<Error>' cannot be assigned to anything
let y = x[123] // Error: type '<Error>' cannot be assigned to anything
let y = x[Symbol("ABCD")] // Error: type '<Error>' cannot be assigned to anything
Or even:
x["d"] = <null> {}; // Error: type 'null' is not assignable to '<Error>'
x["d"] = <undefined> {}; // Error: type 'undefined' is not assignable to '<Error>'
x["d"] = <void> {}; // Error: type 'void' is not assignable to '<Error>'
x["d"] = <any> {}; // Error: type 'any' is not assignable to '<Error>'
Open questions:
- What would be the implications in terms of indexing into an entity having this signature in its type?
- What would be the implications in terms of assigning to an entity having this signature in its type?
- What would be the implications in terms of assigning from an entity having this signature in its type?
- Would adding
[key: any...]: <Error>convert any interface to a "strict" interface? (i.e. one that cannot be assigned from a 'wider' type containing more properties). And if it would, would that be seen as desirable or useful?
Edits: expanded and corrected examples to the actual behavior with noImplicitAny enabled.
Edits: converted from 'bottom' to <Error> as I seemed to have used a less common interpretation of the 'bottom' type
Edits (13 May 2016): changed [...] to [key: ...any] for better consistency with the current syntax.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
この issue の例と未解決の質問から始め、続いて #5683、#7656、#7660 の関連する議論を読んでください。名前が指定されたファイルやテストはありません。実装のスコープを決める前に、rest index signatures のセマンティクスと構文、およびエラー型を確定する必要があります。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 25/100