Fix check for get/set recommendation (#34885)

* Added more tests.

* Accepted baselines.

* Work better with any parameter type.

* Accepted baselines.

* Use the actual indexed expression.

* Add tests that exhibit bad stringification.

* Accepted baselines.

* Short-circuit stringification on 'undefined'.

* Accepted baselines.

* Remove space.

* Accepted baselines.
This commit is contained in:
Daniel Rosenwasser
2019-11-19 13:00:24 -08:00
committed by GitHub
parent 0bbeab6e61
commit b50b9e0fd2
9 changed files with 798 additions and 114 deletions
+5 -7
View File
@@ -11995,7 +11995,7 @@ namespace ts {
}
}
else {
const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression);
const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType);
if (suggestion !== undefined) {
error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion);
}
@@ -23154,15 +23154,13 @@ namespace ts {
return suggestion && symbolName(suggestion);
}
function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression): string | undefined {
function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression, keyedType: Type): string | undefined {
// check if object type has setter or getter
const hasProp = (name: "set" | "get", argCount = 1) => {
function hasProp(name: "set" | "get") {
const prop = getPropertyOfObjectType(objectType, <__String>name);
if (prop) {
const s = getSingleCallSignature(getTypeOfSymbol(prop));
if (s && getMinArgumentCount(s) === argCount && typeToString(getTypeAtPosition(s, 0)) === "string") {
return true;
}
return !!s && getMinArgumentCount(s) >= 1 && isTypeAssignableTo(keyedType, getTypeAtPosition(s, 0));
}
return false;
};
@@ -23172,7 +23170,7 @@ namespace ts {
return undefined;
}
let suggestion = tryGetPropertyAccessOrIdentifierToString(expr);
let suggestion = tryGetPropertyAccessOrIdentifierToString(expr.expression);
if (suggestion === undefined) {
suggestion = suggestedMethod;
}
+1 -1
View File
@@ -4518,7 +4518,7 @@
"category": "Error",
"code": 7051
},
"Element implicitly has an 'any' type because type '{0}' has no index signature. Did you mean to call '{1}' ?": {
"Element implicitly has an 'any' type because type '{0}' has no index signature. Did you mean to call '{1}'?": {
"category": "Error",
"code": 7052
},
+5 -2
View File
@@ -4244,9 +4244,12 @@ namespace ts {
export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): string | undefined {
if (isPropertyAccessExpression(expr)) {
return tryGetPropertyAccessOrIdentifierToString(expr.expression) + "." + expr.name;
const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression);
if (baseStr !== undefined) {
return baseStr + "." + expr.name;
}
}
if (isIdentifier(expr)) {
else if (isIdentifier(expr)) {
return unescapeLeadingUnderscores(expr.escapedText);
}
return undefined;
+1
View File
@@ -901,6 +901,7 @@ namespace ts.NavigationBar {
return "<function>";
}
// See also 'tryGetPropertyAccessOrIdentifierToString'
function getCalledExpressionName(expr: Expression): string | undefined {
if (isIdentifier(expr)) {
return expr.text;
@@ -1,25 +1,43 @@
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(1,9): error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{}'.
Property 'hello' does not exist on type '{}'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(7,1): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'get' ?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(8,13): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'get' ?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(7,1): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'c.get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(8,13): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'c.get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(13,13): error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{ set: (key: string) => string; }'.
Property 'hello' does not exist on type '{ set: (key: string) => string; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(19,1): error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(20,1): error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(21,1): error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(26,1): error TS7053: Element implicitly has an 'any' type because expression of type '"a" | "b" | "c"' can't be used to index type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(20,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(21,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(22,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(23,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(31,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(32,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(33,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(34,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(43,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(44,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(45,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(49,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(50,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(51,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(52,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(56,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'get'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(57,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(58,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(59,3): error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(65,1): error TS7053: Element implicitly has an 'any' type because expression of type '"a" | "b" | "c"' can't be used to index type '{ a: number; }'.
Property 'b' does not exist on type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(30,1): error TS7053: Element implicitly has an 'any' type because expression of type '"c"' can't be used to index type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(69,1): error TS7053: Element implicitly has an 'any' type because expression of type '"c"' can't be used to index type '{ a: number; }'.
Property 'c' does not exist on type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(33,1): error TS7053: Element implicitly has an 'any' type because expression of type 'unique symbol' can't be used to index type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(72,1): error TS7053: Element implicitly has an 'any' type because expression of type 'unique symbol' can't be used to index type '{ a: number; }'.
Property '[sym]' does not exist on type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(37,1): error TS7053: Element implicitly has an 'any' type because expression of type 'NumEnum' can't be used to index type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(76,1): error TS7053: Element implicitly has an 'any' type because expression of type 'NumEnum' can't be used to index type '{ a: number; }'.
Property '[NumEnum.a]' does not exist on type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,1): error TS7053: Element implicitly has an 'any' type because expression of type 'StrEnum' can't be used to index type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(81,1): error TS7053: Element implicitly has an 'any' type because expression of type 'StrEnum' can't be used to index type '{ a: number; }'.
Property '[StrEnum.b]' does not exist on type '{ a: number; }'.
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(93,5): error TS2538: Type 'Dog' cannot be used as an index type.
==== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts (12 errors) ====
==== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts (30 errors) ====
var a = {}["hello"];
~~~~~~~~~~~
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{}'.
@@ -31,10 +49,10 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,1): error TS7053:
};
c['hello'];
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'get' ?
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'c.get'?
const foo = c['hello'];
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'get' ?
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; }' has no index signature. Did you mean to call 'c.get'?
var d = {
set: (key: string) => 'foobar'
@@ -44,19 +62,92 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,1): error TS7053:
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{ set: (key: string) => string; }'.
!!! error TS7053: Property 'hello' does not exist on type '{ set: (key: string) => string; }'.
var e = {
set: (key: string) => 'foobar',
get: (key: string) => 'foobar'
};
e['hello'] = 'modified';
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
e['hello'] += 1;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
e['hello'] ++;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ set: (key: string) => string; get: (key: string) => string; }' has no index signature. Did you mean to call 'set' ?
{
let e = {
get: (key: string) => 'foobar',
set: (key: string) => 'foobar'
};
e['hello'];
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.get'?
e['hello'] = 'modified';
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] += 1;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] ++;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string) => string; }' has no index signature. Did you mean to call 'e.set'?
}
{
let e = {
get: (key: string) => 'foobar',
set: (key: string, value: string) => 'foobar'
};
e['hello'];
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.get'?
e['hello'] = 'modified';
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] += 1;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] ++;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
}
{
let e = {
get: (key: "hello" | "world") => 'foobar',
set: (key: "hello" | "world", value: string) => 'foobar'
};
e['hello'];
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.get'?
e['hello'] = 'modified';
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] += 1;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
e['hello'] ++;
~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }' has no index signature. Did you mean to call 'e.set'?
}
{
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'get'?
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
}
{
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'get'?
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7052: Element implicitly has an 'any' type because type '{ get: (key: string) => string; set: (key: string, value: string) => void; }' has no index signature. Did you mean to call 'set'?
}
const o = { a: 0 };
@@ -93,4 +184,18 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,1): error TS7053:
~~~~~~~~~~~~~
!!! error TS7053: Element implicitly has an 'any' type because expression of type 'StrEnum' can't be used to index type '{ a: number; }'.
!!! error TS7053: Property '[StrEnum.b]' does not exist on type '{ a: number; }'.
interface MyMap<K, T> {
get(key: K): T;
set(key: K, value: T): void;
}
interface Dog { bark(): void; }
let rover: Dog = { bark() {} };
declare let map: MyMap<Dog, string>;
map[rover] = "Rover";
~~~~~
!!! error TS2538: Type 'Dog' cannot be used as an index type.
@@ -13,13 +13,52 @@ var d = {
};
const bar = d['hello'];
var e = {
set: (key: string) => 'foobar',
get: (key: string) => 'foobar'
};
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
{
let e = {
get: (key: string) => 'foobar',
set: (key: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
let e = {
get: (key: string) => 'foobar',
set: (key: string, value: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
let e = {
get: (key: "hello" | "world") => 'foobar',
set: (key: "hello" | "world", value: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'];
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified';
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1;
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++;
}
{
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'];
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified';
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1;
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++;
}
const o = { a: 0 };
@@ -41,6 +80,18 @@ o[numEnumKey];
enum StrEnum { a = "a", b = "b" }
let strEnumKey: StrEnum;
o[strEnumKey];
interface MyMap<K, T> {
get(key: K): T;
set(key: K, value: T): void;
}
interface Dog { bark(): void; }
let rover: Dog = { bark() {} };
declare let map: MyMap<Dog, string>;
map[rover] = "Rover";
//// [noImplicitAnyStringIndexerOnObject.js]
@@ -55,13 +106,48 @@ var d = {
set: function (key) { return 'foobar'; }
};
var bar = d['hello'];
var e = {
set: function (key) { return 'foobar'; },
get: function (key) { return 'foobar'; }
};
e['hello'] = 'modified';
e['hello'] += 1;
e['hello']++;
{
var e = {
get: function (key) { return 'foobar'; },
set: function (key) { return 'foobar'; }
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello']++;
}
{
var e = {
get: function (key) { return 'foobar'; },
set: function (key, value) { return 'foobar'; }
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello']++;
}
{
var e = {
get: function (key) { return 'foobar'; },
set: function (key, value) { return 'foobar'; }
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello']++;
}
{
({ get: function (key) { return 'hello'; }, set: function (key, value) { } })['hello'];
({ get: function (key) { return 'hello'; }, set: function (key, value) { } })['hello'] = 'modified';
({ get: function (key) { return 'hello'; }, set: function (key, value) { } })['hello'] += 1;
({ get: function (key) { return 'hello'; }, set: function (key, value) { } })['hello']++;
}
{
({ foo: { get: function (key) { return 'hello'; }, set: function (key, value) { } } }).foo['hello'];
({ foo: { get: function (key) { return 'hello'; }, set: function (key, value) { } } }).foo['hello'] = 'modified';
({ foo: { get: function (key) { return 'hello'; }, set: function (key, value) { } } }).foo['hello'] += 1;
({ foo: { get: function (key) { return 'hello'; }, set: function (key, value) { } } }).foo['hello']++;
}
var o = { a: 0 };
o[k];
o[k2];
@@ -80,3 +166,5 @@ var StrEnum;
})(StrEnum || (StrEnum = {}));
var strEnumKey;
o[strEnumKey];
var rover = { bark: function () { } };
map[rover] = "Rover";
@@ -34,77 +34,246 @@ const bar = d['hello'];
>bar : Symbol(bar, Decl(noImplicitAnyStringIndexerOnObject.ts, 12, 5))
>d : Symbol(d, Decl(noImplicitAnyStringIndexerOnObject.ts, 9, 3))
var e = {
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 14, 3))
{
let e = {
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 5))
set: (key: string) => 'foobar',
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 14, 9))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 8))
get: (key: string) => 'foobar',
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 16, 10))
get: (key: string) => 'foobar'
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 33))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 16, 8))
set: (key: string) => 'foobar'
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 16, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 17, 10))
};
e['hello'] = 'modified';
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 14, 3))
};
e['hello'];
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 5))
e['hello'] += 1;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 14, 3))
e['hello'] = 'modified';
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 5))
e['hello'] ++;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 14, 3))
e['hello'] += 1;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 5))
e['hello'] ++;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 15, 5))
}
{
let e = {
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 5))
get: (key: string) => 'foobar',
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 27, 10))
set: (key: string, value: string) => 'foobar'
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 27, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 28, 10))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 28, 22))
};
e['hello'];
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 5))
e['hello'] = 'modified';
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 5))
e['hello'] += 1;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 5))
e['hello'] ++;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 26, 5))
}
{
let e = {
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 5))
get: (key: "hello" | "world") => 'foobar',
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 38, 10))
set: (key: "hello" | "world", value: string) => 'foobar'
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 38, 46))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 39, 10))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 39, 33))
};
e['hello'];
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 5))
e['hello'] = 'modified';
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 5))
e['hello'] += 1;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 5))
e['hello'] ++;
>e : Symbol(e, Decl(noImplicitAnyStringIndexerOnObject.ts, 37, 5))
}
{
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'];
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 48, 4))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 48, 11))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 48, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 48, 42))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 48, 54))
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified';
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 49, 4))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 49, 11))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 49, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 49, 42))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 49, 54))
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1;
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 50, 4))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 50, 11))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 50, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 50, 42))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 50, 54))
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++;
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 51, 4))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 51, 11))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 51, 35))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 51, 42))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 51, 54))
}
{
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'];
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 4))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 4))
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 18))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 42))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 49))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 61))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 55, 4))
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified';
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 4))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 4))
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 18))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 42))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 49))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 61))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 56, 4))
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1;
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 4))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 4))
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 18))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 42))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 49))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 61))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 57, 4))
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++;
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 4))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 4))
>get : Symbol(get, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 11))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 18))
>set : Symbol(set, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 42))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 49))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 61))
>foo : Symbol(foo, Decl(noImplicitAnyStringIndexerOnObject.ts, 58, 4))
}
const o = { a: 0 };
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>a : Symbol(a, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 11))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>a : Symbol(a, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 11))
declare const k: "a" | "b" | "c";
>k : Symbol(k, Decl(noImplicitAnyStringIndexerOnObject.ts, 24, 13))
>k : Symbol(k, Decl(noImplicitAnyStringIndexerOnObject.ts, 63, 13))
o[k];
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>k : Symbol(k, Decl(noImplicitAnyStringIndexerOnObject.ts, 24, 13))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>k : Symbol(k, Decl(noImplicitAnyStringIndexerOnObject.ts, 63, 13))
declare const k2: "c";
>k2 : Symbol(k2, Decl(noImplicitAnyStringIndexerOnObject.ts, 28, 13))
>k2 : Symbol(k2, Decl(noImplicitAnyStringIndexerOnObject.ts, 67, 13))
o[k2];
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>k2 : Symbol(k2, Decl(noImplicitAnyStringIndexerOnObject.ts, 28, 13))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>k2 : Symbol(k2, Decl(noImplicitAnyStringIndexerOnObject.ts, 67, 13))
declare const sym : unique symbol;
>sym : Symbol(sym, Decl(noImplicitAnyStringIndexerOnObject.ts, 31, 13))
>sym : Symbol(sym, Decl(noImplicitAnyStringIndexerOnObject.ts, 70, 13))
o[sym];
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>sym : Symbol(sym, Decl(noImplicitAnyStringIndexerOnObject.ts, 31, 13))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>sym : Symbol(sym, Decl(noImplicitAnyStringIndexerOnObject.ts, 70, 13))
enum NumEnum { a, b }
>NumEnum : Symbol(NumEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 32, 7))
>a : Symbol(NumEnum.a, Decl(noImplicitAnyStringIndexerOnObject.ts, 34, 14))
>b : Symbol(NumEnum.b, Decl(noImplicitAnyStringIndexerOnObject.ts, 34, 17))
>NumEnum : Symbol(NumEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 71, 7))
>a : Symbol(NumEnum.a, Decl(noImplicitAnyStringIndexerOnObject.ts, 73, 14))
>b : Symbol(NumEnum.b, Decl(noImplicitAnyStringIndexerOnObject.ts, 73, 17))
let numEnumKey: NumEnum;
>numEnumKey : Symbol(numEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 35, 3))
>NumEnum : Symbol(NumEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 32, 7))
>numEnumKey : Symbol(numEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 74, 3))
>NumEnum : Symbol(NumEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 71, 7))
o[numEnumKey];
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>numEnumKey : Symbol(numEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 35, 3))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>numEnumKey : Symbol(numEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 74, 3))
enum StrEnum { a = "a", b = "b" }
>StrEnum : Symbol(StrEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 36, 14))
>a : Symbol(StrEnum.a, Decl(noImplicitAnyStringIndexerOnObject.ts, 39, 14))
>b : Symbol(StrEnum.b, Decl(noImplicitAnyStringIndexerOnObject.ts, 39, 23))
>StrEnum : Symbol(StrEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 75, 14))
>a : Symbol(StrEnum.a, Decl(noImplicitAnyStringIndexerOnObject.ts, 78, 14))
>b : Symbol(StrEnum.b, Decl(noImplicitAnyStringIndexerOnObject.ts, 78, 23))
let strEnumKey: StrEnum;
>strEnumKey : Symbol(strEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 40, 3))
>StrEnum : Symbol(StrEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 36, 14))
>strEnumKey : Symbol(strEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 79, 3))
>StrEnum : Symbol(StrEnum, Decl(noImplicitAnyStringIndexerOnObject.ts, 75, 14))
o[strEnumKey];
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 22, 5))
>strEnumKey : Symbol(strEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 40, 3))
>o : Symbol(o, Decl(noImplicitAnyStringIndexerOnObject.ts, 61, 5))
>strEnumKey : Symbol(strEnumKey, Decl(noImplicitAnyStringIndexerOnObject.ts, 79, 3))
interface MyMap<K, T> {
>MyMap : Symbol(MyMap, Decl(noImplicitAnyStringIndexerOnObject.ts, 80, 14))
>K : Symbol(K, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 16))
>T : Symbol(T, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 18))
get(key: K): T;
>get : Symbol(MyMap.get, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 23))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 84, 6))
>K : Symbol(K, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 16))
>T : Symbol(T, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 18))
set(key: K, value: T): void;
>set : Symbol(MyMap.set, Decl(noImplicitAnyStringIndexerOnObject.ts, 84, 17))
>key : Symbol(key, Decl(noImplicitAnyStringIndexerOnObject.ts, 85, 6))
>K : Symbol(K, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 16))
>value : Symbol(value, Decl(noImplicitAnyStringIndexerOnObject.ts, 85, 13))
>T : Symbol(T, Decl(noImplicitAnyStringIndexerOnObject.ts, 83, 18))
}
interface Dog { bark(): void; }
>Dog : Symbol(Dog, Decl(noImplicitAnyStringIndexerOnObject.ts, 86, 1))
>bark : Symbol(Dog.bark, Decl(noImplicitAnyStringIndexerOnObject.ts, 88, 15))
let rover: Dog = { bark() {} };
>rover : Symbol(rover, Decl(noImplicitAnyStringIndexerOnObject.ts, 89, 3))
>Dog : Symbol(Dog, Decl(noImplicitAnyStringIndexerOnObject.ts, 86, 1))
>bark : Symbol(bark, Decl(noImplicitAnyStringIndexerOnObject.ts, 89, 18))
declare let map: MyMap<Dog, string>;
>map : Symbol(map, Decl(noImplicitAnyStringIndexerOnObject.ts, 91, 11))
>MyMap : Symbol(MyMap, Decl(noImplicitAnyStringIndexerOnObject.ts, 80, 14))
>Dog : Symbol(Dog, Decl(noImplicitAnyStringIndexerOnObject.ts, 86, 1))
map[rover] = "Rover";
>map : Symbol(map, Decl(noImplicitAnyStringIndexerOnObject.ts, 91, 11))
>rover : Symbol(rover, Decl(noImplicitAnyStringIndexerOnObject.ts, 89, 3))
@@ -52,42 +52,281 @@ const bar = d['hello'];
>d : { set: (key: string) => string; }
>'hello' : "hello"
var e = {
>e : { set: (key: string) => string; get: (key: string) => string; }
>{ set: (key: string) => 'foobar', get: (key: string) => 'foobar'} : { set: (key: string) => string; get: (key: string) => string; }
{
let e = {
>e : { get: (key: string) => string; set: (key: string) => string; }
>{ get: (key: string) => 'foobar', set: (key: string) => 'foobar' } : { get: (key: string) => string; set: (key: string) => string; }
set: (key: string) => 'foobar',
>set : (key: string) => string
>(key: string) => 'foobar' : (key: string) => string
>key : string
>'foobar' : "foobar"
get: (key: string) => 'foobar'
get: (key: string) => 'foobar',
>get : (key: string) => string
>(key: string) => 'foobar' : (key: string) => string
>key : string
>'foobar' : "foobar"
};
e['hello'] = 'modified';
set: (key: string) => 'foobar'
>set : (key: string) => string
>(key: string) => 'foobar' : (key: string) => string
>key : string
>'foobar' : "foobar"
};
e['hello'];
>e['hello'] : any
>e : { get: (key: string) => string; set: (key: string) => string; }
>'hello' : "hello"
e['hello'] = 'modified';
>e['hello'] = 'modified' : "modified"
>e['hello'] : any
>e : { set: (key: string) => string; get: (key: string) => string; }
>e : { get: (key: string) => string; set: (key: string) => string; }
>'hello' : "hello"
>'modified' : "modified"
e['hello'] += 1;
e['hello'] += 1;
>e['hello'] += 1 : any
>e['hello'] : any
>e : { set: (key: string) => string; get: (key: string) => string; }
>e : { get: (key: string) => string; set: (key: string) => string; }
>'hello' : "hello"
>1 : 1
e['hello'] ++;
e['hello'] ++;
>e['hello'] ++ : number
>e['hello'] : any
>e : { set: (key: string) => string; get: (key: string) => string; }
>e : { get: (key: string) => string; set: (key: string) => string; }
>'hello' : "hello"
}
{
let e = {
>e : { get: (key: string) => string; set: (key: string, value: string) => string; }
>{ get: (key: string) => 'foobar', set: (key: string, value: string) => 'foobar' } : { get: (key: string) => string; set: (key: string, value: string) => string; }
get: (key: string) => 'foobar',
>get : (key: string) => string
>(key: string) => 'foobar' : (key: string) => string
>key : string
>'foobar' : "foobar"
set: (key: string, value: string) => 'foobar'
>set : (key: string, value: string) => string
>(key: string, value: string) => 'foobar' : (key: string, value: string) => string
>key : string
>value : string
>'foobar' : "foobar"
};
e['hello'];
>e['hello'] : any
>e : { get: (key: string) => string; set: (key: string, value: string) => string; }
>'hello' : "hello"
e['hello'] = 'modified';
>e['hello'] = 'modified' : "modified"
>e['hello'] : any
>e : { get: (key: string) => string; set: (key: string, value: string) => string; }
>'hello' : "hello"
>'modified' : "modified"
e['hello'] += 1;
>e['hello'] += 1 : any
>e['hello'] : any
>e : { get: (key: string) => string; set: (key: string, value: string) => string; }
>'hello' : "hello"
>1 : 1
e['hello'] ++;
>e['hello'] ++ : number
>e['hello'] : any
>e : { get: (key: string) => string; set: (key: string, value: string) => string; }
>'hello' : "hello"
}
{
let e = {
>e : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
>{ get: (key: "hello" | "world") => 'foobar', set: (key: "hello" | "world", value: string) => 'foobar' } : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
get: (key: "hello" | "world") => 'foobar',
>get : (key: "hello" | "world") => string
>(key: "hello" | "world") => 'foobar' : (key: "hello" | "world") => string
>key : "hello" | "world"
>'foobar' : "foobar"
set: (key: "hello" | "world", value: string) => 'foobar'
>set : (key: "hello" | "world", value: string) => string
>(key: "hello" | "world", value: string) => 'foobar' : (key: "hello" | "world", value: string) => string
>key : "hello" | "world"
>value : string
>'foobar' : "foobar"
};
e['hello'];
>e['hello'] : any
>e : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
>'hello' : "hello"
e['hello'] = 'modified';
>e['hello'] = 'modified' : "modified"
>e['hello'] : any
>e : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
>'hello' : "hello"
>'modified' : "modified"
e['hello'] += 1;
>e['hello'] += 1 : any
>e['hello'] : any
>e : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
>'hello' : "hello"
>1 : 1
e['hello'] ++;
>e['hello'] ++ : number
>e['hello'] : any
>e : { get: (key: "hello" | "world") => string; set: (key: "hello" | "world", value: string) => string; }
>'hello' : "hello"
}
{
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'];
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] : any
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} }) : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>'hello' : "hello"
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified';
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified' : "modified"
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] : any
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} }) : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>'hello' : "hello"
>'modified' : "modified"
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1;
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1 : any
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] : any
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} }) : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>'hello' : "hello"
>1 : 1
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++;
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++ : number
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] : any
>({ get: (key: string) => 'hello', set: (key: string, value: string) => {} }) : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>'hello' : "hello"
}
{
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'];
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] : any
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }) : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>{ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } } : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>'hello' : "hello"
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified';
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified' : "modified"
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] : any
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }) : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>{ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } } : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>'hello' : "hello"
>'modified' : "modified"
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1;
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1 : any
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] : any
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }) : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>{ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } } : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>'hello' : "hello"
>1 : 1
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++;
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++ : number
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] : any
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }) : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>{ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } } : { foo: { get: (key: string) => string; set: (key: string, value: string) => void; }; }
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>{ get: (key: string) => 'hello', set: (key: string, value: string) => {} } : { get: (key: string) => string; set: (key: string, value: string) => void; }
>get : (key: string) => string
>(key: string) => 'hello' : (key: string) => string
>key : string
>'hello' : "hello"
>set : (key: string, value: string) => void
>(key: string, value: string) => {} : (key: string, value: string) => void
>key : string
>value : string
>foo : { get: (key: string) => string; set: (key: string, value: string) => void; }
>'hello' : "hello"
}
const o = { a: 0 };
>o : { a: number; }
@@ -149,3 +388,33 @@ o[strEnumKey];
>o : { a: number; }
>strEnumKey : StrEnum
interface MyMap<K, T> {
get(key: K): T;
>get : (key: K) => T
>key : K
set(key: K, value: T): void;
>set : (key: K, value: T) => void
>key : K
>value : T
}
interface Dog { bark(): void; }
>bark : () => void
let rover: Dog = { bark() {} };
>rover : Dog
>{ bark() {} } : { bark(): void; }
>bark : () => void
declare let map: MyMap<Dog, string>;
>map : MyMap<Dog, string>
map[rover] = "Rover";
>map[rover] = "Rover" : "Rover"
>map[rover] : any
>map : MyMap<Dog, string>
>rover : Dog
>"Rover" : "Rover"
@@ -14,13 +14,52 @@ var d = {
};
const bar = d['hello'];
var e = {
set: (key: string) => 'foobar',
get: (key: string) => 'foobar'
};
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
{
let e = {
get: (key: string) => 'foobar',
set: (key: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
let e = {
get: (key: string) => 'foobar',
set: (key: string, value: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
let e = {
get: (key: "hello" | "world") => 'foobar',
set: (key: "hello" | "world", value: string) => 'foobar'
};
e['hello'];
e['hello'] = 'modified';
e['hello'] += 1;
e['hello'] ++;
}
{
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'];
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] = 'modified';
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] += 1;
({ get: (key: string) => 'hello', set: (key: string, value: string) => {} })['hello'] ++;
}
{
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'];
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] = 'modified';
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] += 1;
({ foo: { get: (key: string) => 'hello', set: (key: string, value: string) => {} } }).foo['hello'] ++;
}
const o = { a: 0 };
@@ -42,3 +81,15 @@ o[numEnumKey];
enum StrEnum { a = "a", b = "b" }
let strEnumKey: StrEnum;
o[strEnumKey];
interface MyMap<K, T> {
get(key: K): T;
set(key: K, value: T): void;
}
interface Dog { bark(): void; }
let rover: Dog = { bark() {} };
declare let map: MyMap<Dog, string>;
map[rover] = "Rover";