Ensure that numeric names are in their printed form.

This commit is contained in:
Daniel Rosenwasser 2014-10-09 12:50:01 -07:00
parent 5a49bb610a
commit 13b5fe0573
6 changed files with 174 additions and 102 deletions

View File

@ -4094,6 +4094,13 @@ module ts {
var numericScanner: Scanner;
function isNumericName(name: string) {
// First see if the name is in canonical string representation.
// Unfortunately this permits various forms of "NaN" and "Infinity",
// but it is a good check to save time.
if ((+name).toString() !== name) {
return false;
}
numericScanner = numericScanner || createScanner(compilerOptions.target || ScriptTarget.ES5, /*skipTrivia*/ false);
numericScanner.setText(name);
@ -4101,10 +4108,11 @@ module ts {
// (i.e. it is preceded by nothing and scanning leaves us at the very end of the string).
var token = numericScanner.scan();
if (token === SyntaxKind.MinusToken || token === SyntaxKind.PlusToken) {
// '+' will never be in front of a number in its printed form.
if (token === SyntaxKind.MinusToken) {
token = numericScanner.scan();
}
return token === SyntaxKind.NumericLiteral && numericScanner.getTextPos() === name.length;
}
@ -4158,7 +4166,9 @@ module ts {
if (hasProperty(properties, id)) {
if (kind === IndexKind.String || isNumericName(id)) {
var type = getTypeOfSymbol(properties[id]);
if (!contains(propTypes, type)) propTypes.push(type);
if (!contains(propTypes, type)) {
propTypes.push(type);
}
}
}
}

View File

@ -4,19 +4,16 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(90,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(93,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(18,5): error TS2412: Property '2.0' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(20,5): error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(21,5): error TS2412: Property '3.0' of type 'MyNumber' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(50,5): error TS2412: Property '2.0' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(55,5): error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(68,5): error TS2412: Property '2.0' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(73,5): error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(78,5): error TS2322: Type '{ [x: number]: {}; 1.0: string; 2.0: number; a: string; b: number; c: () => void; "d": string; "e": number; "3.0": string; "4.0": number; f: unknown; X: string; foo: () => string; }' is not assignable to type '{ [x: number]: string; }':
Index signatures are incompatible:
Type '{}' is not assignable to type 'string'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts(88,9): error TS2304: Cannot find name 'Myn'.
==== tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts (14 errors) ====
==== tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations.ts (11 errors) ====
// String indexer types constrain the types of named properties in their containing type
interface MyNumber extends Number {
@ -39,8 +36,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
!!! error TS2412: Property '2.0' of type 'number' is not assignable to numeric index type 'string'.
"3.0": string; // ok
"4.0": number; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
3.0: MyNumber // error
~~~~~~~~~~~~~
!!! error TS2412: Property '3.0' of type 'MyNumber' is not assignable to numeric index type 'string'.
@ -86,8 +81,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
foo(): string; // ok
"3.0": string; // ok
"4.0": number; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
f: MyNumber; // error
}
@ -108,8 +101,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
foo(): string; // ok
"3.0": string; // ok
"4.0": number; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'number' is not assignable to numeric index type 'string'.
f: MyNumber; // error
}

View File

@ -1,16 +1,13 @@
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(16,5): error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(17,5): error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(25,5): error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(26,5): error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(34,5): error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(35,5): error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts(39,5): error TS2322: Type '{ [x: number]: {}; 1.0: A; 2.0: B; 3.0: number; "2.5": B; "4.0": string; }' is not assignable to type '{ [x: number]: A; }':
Index signatures are incompatible:
Type '{}' is not assignable to type 'A':
Property 'foo' is missing in type '{}'.
==== tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts (7 errors) ====
==== tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerConstrainsPropertyDeclarations2.ts (4 errors) ====
// String indexer providing a constraint of a user defined type
class A {
@ -30,8 +27,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
~~~~~~~~~~~~
!!! error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
"4.0": string; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
}
interface Foo2 {
@ -43,8 +38,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
~~~~~~~~~~~~
!!! error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
"4.0": string; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
}
var a: {
@ -56,8 +49,6 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/numericIndexerCo
~~~~~~~~~~~~
!!! error TS2412: Property '3.0' of type 'number' is not assignable to numeric index type 'A'.
"4.0": string; // error
~~~~~~~~~~~~~~
!!! error TS2412: Property '"4.0"' of type 'string' is not assignable to numeric index type 'A'.
};
// error

View File

@ -1,29 +1,54 @@
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(3,3): error TS2412: Property '"1"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(4,3): error TS2412: Property '"-1"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(5,3): error TS2412: Property '"+1"' of type 'string' is not assignable to numeric index type 'number'.
==== tests/cases/compiler/propertiesAndIndexersForNumericNames.ts (3 errors) ====
class C {
[i: number]: number;
public "1": string = "number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"1"' of type 'string' is not assignable to numeric index type 'number'.
public "-1": string = "negative number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"-1"' of type 'string' is not assignable to numeric index type 'number'.
public "+1": string = "positive number (for the paranoid)"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"+1"' of type 'string' is not assignable to numeric index type 'number'.
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
}
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(6,5): error TS2412: Property '"1"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(7,5): error TS2412: Property '"-1"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(8,5): error TS2412: Property '"-2.5"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(9,5): error TS2412: Property '"3.141592"' of type 'string' is not assignable to numeric index type 'number'.
tests/cases/compiler/propertiesAndIndexersForNumericNames.ts(10,5): error TS2412: Property '"1.2e-20"' of type 'string' is not assignable to numeric index type 'number'.
==== tests/cases/compiler/propertiesAndIndexersForNumericNames.ts (5 errors) ====
class C {
[i: number]: number;
// These all have numeric names; they should error
// because their types are not compatible with the numeric indexer.
public "1": string = "number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"1"' of type 'string' is not assignable to numeric index type 'number'.
public "-1": string = "negative number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"-1"' of type 'string' is not assignable to numeric index type 'number'.
public "-2.5": string = "negative number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"-2.5"' of type 'string' is not assignable to numeric index type 'number'.
public "3.141592": string = "pi-sitive number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"3.141592"' of type 'string' is not assignable to numeric index type 'number'.
public "1.2e-20": string = "really small number"; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2412: Property '"1.2e-20"' of type 'string' is not assignable to numeric index type 'number'.
// These all have *partially* numeric names,
// but should really be treated as plain string literals.
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "hunter2": string = "not a password"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
// These fall into the above category, however, they are "trickier";
// these all are *scanned* as numeric literals, but they are not written in
// "canonical" numeric representations.
public "+1": string = "positive number (for the paranoid)"; // No error
public "1e0": string = "just one"; // No error
public "-0e0": string = "just zero"; // No error
public "0xF00D": string = "hex food"; // No error
public "0xBEEF": string = "hex beef"; // No error
public "0123": string = "oct 83"; // No error
public "0.000000000000000000012": string = "should've been in exponential form"; // No error
}

View File

@ -1,37 +1,73 @@
//// [propertiesAndIndexersForNumericNames.ts]
//// [propertiesAndIndexersForNumericNames.ts]
class C {
[i: number]: number;
public "1": string = "number"; // Error
public "-1": string = "negative number"; // Error
public "+1": string = "positive number (for the paranoid)"; // Error
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
[i: number]: number;
// These all have numeric names; they should error
// because their types are not compatible with the numeric indexer.
public "1": string = "number"; // Error
public "-1": string = "negative number"; // Error
public "-2.5": string = "negative number"; // Error
public "3.141592": string = "pi-sitive number"; // Error
public "1.2e-20": string = "really small number"; // Error
// These all have *partially* numeric names,
// but should really be treated as plain string literals.
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "hunter2": string = "not a password"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
// These fall into the above category, however, they are "trickier";
// these all are *scanned* as numeric literals, but they are not written in
// "canonical" numeric representations.
public "+1": string = "positive number (for the paranoid)"; // No error
public "1e0": string = "just one"; // No error
public "-0e0": string = "just zero"; // No error
public "0xF00D": string = "hex food"; // No error
public "0xBEEF": string = "hex beef"; // No error
public "0123": string = "oct 83"; // No error
public "0.000000000000000000012": string = "should've been in exponential form"; // No error
}
//// [propertiesAndIndexersForNumericNames.js]
var C = (function () {
function C() {
this["1"] = "number"; // Error
this["-1"] = "negative number"; // Error
this["+1"] = "positive number (for the paranoid)"; // Error
this[" 1"] = "leading space"; // No error
this["1 "] = "trailing space"; // No error
this[""] = "no nothing"; // No error
this[" "] = "just space"; // No error
this["1 0 1"] = "several numbers and spaces"; // No error
this["NaN"] = "not a number"; // No error
this["-NaN"] = "not a negative number"; // No error
this["+Infinity"] = "A gillion"; // No error
this["-Infinity"] = "Negative-a-gillion"; // No error
}
return C;
})();
//// [propertiesAndIndexersForNumericNames.js]
var C = (function () {
function C() {
// These all have numeric names; they should error
// because their types are not compatible with the numeric indexer.
this["1"] = "number"; // Error
this["-1"] = "negative number"; // Error
this["-2.5"] = "negative number"; // Error
this["3.141592"] = "pi-sitive number"; // Error
this["1.2e-20"] = "really small number"; // Error
// These all have *partially* numeric names,
// but should really be treated as plain string literals.
this[" 1"] = "leading space"; // No error
this["1 "] = "trailing space"; // No error
this[""] = "no nothing"; // No error
this[" "] = "just space"; // No error
this["1 0 1"] = "several numbers and spaces"; // No error
this["NaN"] = "not a number"; // No error
this["-NaN"] = "not a negative number"; // No error
this["hunter2"] = "not a password"; // No error
this["+Infinity"] = "A gillion"; // No error
this["-Infinity"] = "Negative-a-gillion"; // No error
// These fall into the above category, however, they are "trickier";
// these all are *scanned* as numeric literals, but they are not written in
// "canonical" numeric representations.
this["+1"] = "positive number (for the paranoid)"; // No error
this["1e0"] = "just one"; // No error
this["-0e0"] = "just zero"; // No error
this["0xF00D"] = "hex food"; // No error
this["0xBEEF"] = "hex beef"; // No error
this["0123"] = "oct 83"; // No error
this["0.000000000000000000012"] = "should've been in exponential form"; // No error
}
return C;
})();

View File

@ -1,16 +1,35 @@
class C {
[i: number]: number;
public "1": string = "number"; // Error
public "-1": string = "negative number"; // Error
public "+1": string = "positive number (for the paranoid)"; // Error
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
}
class C {
[i: number]: number;
// These all have numeric names; they should error
// because their types are not compatible with the numeric indexer.
public "1": string = "number"; // Error
public "-1": string = "negative number"; // Error
public "-2.5": string = "negative number"; // Error
public "3.141592": string = "pi-sitive number"; // Error
public "1.2e-20": string = "really small number"; // Error
// These all have *partially* numeric names,
// but should really be treated as plain string literals.
public " 1": string = "leading space"; // No error
public "1 ": string = "trailing space"; // No error
public "": string = "no nothing"; // No error
public " ": string = "just space"; // No error
public "1 0 1": string = "several numbers and spaces"; // No error
public "NaN": string = "not a number"; // No error
public "-NaN": string = "not a negative number"; // No error
public "hunter2": string = "not a password"; // No error
public "+Infinity": string = "A gillion"; // No error
public "-Infinity": string = "Negative-a-gillion"; // No error
// These fall into the above category, however, they are "trickier";
// these all are *scanned* as numeric literals, but they are not written in
// "canonical" numeric representations.
public "+1": string = "positive number (for the paranoid)"; // No error
public "1e0": string = "just one"; // No error
public "-0e0": string = "just zero"; // No error
public "0xF00D": string = "hex food"; // No error
public "0xBEEF": string = "hex beef"; // No error
public "0123": string = "oct 83"; // No error
public "0.000000000000000000012": string = "should've been in exponential form"; // No error
}