Merge pull request #12671 from Microsoft/property-access-for-string-index-sigs

Property access for string index signatures
This commit is contained in:
Nathan Shively-Sanders
2017-01-18 08:38:33 -08:00
committed by GitHub
14 changed files with 123 additions and 23 deletions

View File

@@ -12444,6 +12444,10 @@ namespace ts {
}
const prop = getPropertyOfType(apparentType, right.text);
if (!prop) {
const stringIndexType = getIndexTypeOfType(apparentType, IndexKind.String);
if (stringIndexType) {
return stringIndexType;
}
if (right.text && !checkAndReportErrorForExtendingInterface(node)) {
reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type);
}

View File

@@ -44,7 +44,7 @@ let computed2 = 'a';
var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o;
({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o);
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject['anythingGoes'];
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;
//// [objectRest.js]
@@ -89,6 +89,6 @@ var _g = computed, stillNotGreat = o[_g], _h = computed2, soSo = o[_h], o = __re
(_j = computed, stillNotGreat = o[_j], _k = computed2, soSo = o[_k], o = __rest(o, [typeof _j === "symbol" ? _j : _j + "", typeof _k === "symbol" ? _k : _k + ""]));
var noContextualType = (_a) => {
var { aNumber = 12 } = _a, notEmptyObject = __rest(_a, ["aNumber"]);
return aNumber + notEmptyObject['anythingGoes'];
return aNumber + notEmptyObject.anythingGoes;
};
var _d, _f, _j, _k;

View File

@@ -191,7 +191,7 @@ var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o;
>o : Symbol(o, Decl(objectRest.ts, 0, 3), Decl(objectRest.ts, 42, 51))
>o : Symbol(o, Decl(objectRest.ts, 0, 3), Decl(objectRest.ts, 42, 51))
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject['anythingGoes'];
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;
>noContextualType : Symbol(noContextualType, Decl(objectRest.ts, 45, 3))
>aNumber : Symbol(aNumber, Decl(objectRest.ts, 45, 25))
>notEmptyObject : Symbol(notEmptyObject, Decl(objectRest.ts, 45, 39))

View File

@@ -217,15 +217,15 @@ var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o;
>o : { a: number; b: string; }
>o : { a: number; b: string; }
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject['anythingGoes'];
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;
>noContextualType : ({aNumber, ...notEmptyObject}: { [x: string]: any; aNumber?: number; }) => any
>({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject['anythingGoes'] : ({aNumber, ...notEmptyObject}: { [x: string]: any; aNumber?: number; }) => any
>({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes : ({aNumber, ...notEmptyObject}: { [x: string]: any; aNumber?: number; }) => any
>aNumber : number
>12 : 12
>notEmptyObject : { [x: string]: any; }
>aNumber + notEmptyObject['anythingGoes'] : any
>aNumber + notEmptyObject.anythingGoes : any
>aNumber : number
>notEmptyObject['anythingGoes'] : any
>notEmptyObject.anythingGoes : any
>notEmptyObject : { [x: string]: any; }
>'anythingGoes' : "anythingGoes"
>anythingGoes : any

View File

@@ -7,10 +7,9 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(11,30): error TS7008: M
tests/cases/conformance/types/rest/objectRestNegative.ts(11,33): error TS7008: Member 'y' implicitly has an 'any' type.
tests/cases/conformance/types/rest/objectRestNegative.ts(12,17): error TS2700: Rest types may only be created from object types.
tests/cases/conformance/types/rest/objectRestNegative.ts(17,9): error TS2701: The target of an object rest assignment must be a variable or a property access.
tests/cases/conformance/types/rest/objectRestNegative.ts(19,90): error TS2339: Property 'anythingGoes' does not exist on type '{ [x: string]: any; }'.
==== tests/cases/conformance/types/rest/objectRestNegative.ts (8 errors) ====
==== tests/cases/conformance/types/rest/objectRestNegative.ts (7 errors) ====
let o = { a: 1, b: 'no' };
var { ...mustBeLast, a } = o;
~~~~~~~~~~
@@ -44,8 +43,4 @@ tests/cases/conformance/types/rest/objectRestNegative.ts(19,90): error TS2339: P
({a, ...rest.b + rest.b} = o);
~~~~~~~~~~~~~~~
!!! error TS2701: The target of an object rest assignment must be a variable or a property access.
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;
~~~~~~~~~~~~
!!! error TS2339: Property 'anythingGoes' does not exist on type '{ [x: string]: any; }'.

View File

@@ -16,8 +16,6 @@ function generic<T extends { x, y }>(t: T) {
let rest: { b: string }
({a, ...rest.b + rest.b} = o);
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;
//// [objectRestNegative.js]
@@ -44,7 +42,3 @@ function generic(t) {
}
var rest;
(a = o.a, o, rest.b + rest.b = __rest(o, ["a"]));
var noContextualType = function (_a) {
var _b = _a.aNumber, aNumber = _b === void 0 ? 12 : _b, notEmptyObject = __rest(_a, ["aNumber"]);
return aNumber + notEmptyObject.anythingGoes;
};

View File

@@ -0,0 +1,18 @@
tests/cases/conformance/expressions/propertyAccess/propertyAccessStringIndexSignature.ts(10,7): error TS2339: Property 'nope' does not exist on type 'Empty'.
==== tests/cases/conformance/expressions/propertyAccess/propertyAccessStringIndexSignature.ts (1 errors) ====
interface Flags { [name: string]: boolean };
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
~~~~
!!! error TS2339: Property 'nope' does not exist on type 'Empty'.
empty["that's ok"];

View File

@@ -0,0 +1,24 @@
//// [propertyAccessStringIndexSignature.ts]
interface Flags { [name: string]: boolean };
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
empty["that's ok"];
//// [propertyAccessStringIndexSignature.js]
;
var flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
var empty;
empty.nope;
empty["that's ok"];

View File

@@ -0,0 +1,21 @@
tests/cases/conformance/expressions/propertyAccess/propertyAccessStringIndexSignatureNoImplicitAny.ts(10,7): error TS2339: Property 'nope' does not exist on type 'Empty'.
tests/cases/conformance/expressions/propertyAccess/propertyAccessStringIndexSignatureNoImplicitAny.ts(11,1): error TS7017: Element implicitly has an 'any' type because type 'Empty' has no index signature.
==== tests/cases/conformance/expressions/propertyAccess/propertyAccessStringIndexSignatureNoImplicitAny.ts (2 errors) ====
interface Flags { [name: string]: boolean }
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
~~~~
!!! error TS2339: Property 'nope' does not exist on type 'Empty'.
empty["not allowed either"];
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS7017: Element implicitly has an 'any' type because type 'Empty' has no index signature.

View File

@@ -0,0 +1,23 @@
//// [propertyAccessStringIndexSignatureNoImplicitAny.ts]
interface Flags { [name: string]: boolean }
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
empty["not allowed either"];
//// [propertyAccessStringIndexSignatureNoImplicitAny.js]
var flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
var empty;
empty.nope;
empty["not allowed either"];

View File

@@ -0,0 +1,11 @@
interface Flags { [name: string]: boolean };
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
empty["that's ok"];

View File

@@ -0,0 +1,12 @@
// @noImplicitAny: true
interface Flags { [name: string]: boolean }
let flags: Flags;
flags.b;
flags.f;
flags.isNotNecessarilyNeverFalse;
flags['this is fine'];
interface Empty { }
let empty: Empty;
empty.nope;
empty["not allowed either"];

View File

@@ -44,4 +44,4 @@ let computed2 = 'a';
var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o;
({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o);
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject['anythingGoes'];
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;

View File

@@ -16,5 +16,3 @@ function generic<T extends { x, y }>(t: T) {
let rest: { b: string }
({a, ...rest.b + rest.b} = o);
var noContextualType = ({ aNumber = 12, ...notEmptyObject }) => aNumber + notEmptyObject.anythingGoes;