Add index signature for anonymous object literal type (#37903)
* Use ts.map for stylistic consistency * Show error only if noImplicitAny is set * Accept baseline for noImplicitAnyIndexing * Fix lint error * Add test cases for indexedAccessWithFreshObjectLiteral
This commit is contained in:
parent
f646ec87fc
commit
7db5f68144
|
@ -13878,6 +13878,19 @@ namespace ts {
|
|||
return anyType;
|
||||
}
|
||||
if (accessExpression && !isConstEnumObjectType(objectType)) {
|
||||
if (isObjectLiteralType(objectType)) {
|
||||
if (noImplicitAny && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
|
||||
diagnostics.add(createDiagnosticForNode(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType)));
|
||||
return undefinedType;
|
||||
}
|
||||
else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) {
|
||||
const types = map((<ResolvedType>objectType).properties, property => {
|
||||
return getTypeOfSymbol(property);
|
||||
});
|
||||
return getUnionType(append(types, undefinedType));
|
||||
}
|
||||
}
|
||||
|
||||
if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) {
|
||||
error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts(34,10): error TS2339: Property 'z' does not exist on type '{ a: number; b: string; c: boolean; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts (1 errors) ====
|
||||
function foo (id: string) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: true
|
||||
}[id]
|
||||
}
|
||||
|
||||
function bar (id: 'a' | 'b') {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function baz (id: '1' | '2') {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function qux (id: 1 | 2) {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function quux (id: 'a' | 'b' | 'z') {
|
||||
return {
|
||||
~
|
||||
a: 1,
|
||||
~~~~~~~~~~~
|
||||
b: "",
|
||||
~~~~~~~~~~~~
|
||||
c: false
|
||||
~~~~~~~~~~~~~~
|
||||
}[id]
|
||||
~~~~~~~
|
||||
!!! error TS2339: Property 'z' does not exist on type '{ a: number; b: string; c: boolean; }'.
|
||||
}
|
||||
|
||||
function corge(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as Record<string, number | string>)[id]
|
||||
}
|
||||
|
||||
function grault(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as { [k: string]: string | number})[id]
|
||||
}
|
||||
|
105
tests/baselines/reference/indexedAccessWithFreshObjectLiteral.js
Normal file
105
tests/baselines/reference/indexedAccessWithFreshObjectLiteral.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
//// [indexedAccessWithFreshObjectLiteral.ts]
|
||||
function foo (id: string) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: true
|
||||
}[id]
|
||||
}
|
||||
|
||||
function bar (id: 'a' | 'b') {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function baz (id: '1' | '2') {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function qux (id: 1 | 2) {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function quux (id: 'a' | 'b' | 'z') {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function corge(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as Record<string, number | string>)[id]
|
||||
}
|
||||
|
||||
function grault(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as { [k: string]: string | number})[id]
|
||||
}
|
||||
|
||||
|
||||
//// [indexedAccessWithFreshObjectLiteral.js]
|
||||
"use strict";
|
||||
function foo(id) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: true
|
||||
}[id];
|
||||
}
|
||||
function bar(id) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id];
|
||||
}
|
||||
function baz(id) {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id];
|
||||
}
|
||||
function qux(id) {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id];
|
||||
}
|
||||
function quux(id) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id];
|
||||
}
|
||||
function corge(id) {
|
||||
return {
|
||||
a: 123,
|
||||
b: ""
|
||||
}[id];
|
||||
}
|
||||
function grault(id) {
|
||||
return {
|
||||
a: 123,
|
||||
b: ""
|
||||
}[id];
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
=== tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts ===
|
||||
function foo (id: string) {
|
||||
>foo : Symbol(foo, Decl(indexedAccessWithFreshObjectLiteral.ts, 0, 0))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 0, 14))
|
||||
|
||||
return {
|
||||
a: 1,
|
||||
>a : Symbol(a, Decl(indexedAccessWithFreshObjectLiteral.ts, 1, 10))
|
||||
|
||||
b: "",
|
||||
>b : Symbol(b, Decl(indexedAccessWithFreshObjectLiteral.ts, 2, 11))
|
||||
|
||||
c: true
|
||||
>c : Symbol(c, Decl(indexedAccessWithFreshObjectLiteral.ts, 3, 12))
|
||||
|
||||
}[id]
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 0, 14))
|
||||
}
|
||||
|
||||
function bar (id: 'a' | 'b') {
|
||||
>bar : Symbol(bar, Decl(indexedAccessWithFreshObjectLiteral.ts, 6, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 8, 14))
|
||||
|
||||
return {
|
||||
a: 1,
|
||||
>a : Symbol(a, Decl(indexedAccessWithFreshObjectLiteral.ts, 9, 10))
|
||||
|
||||
b: "",
|
||||
>b : Symbol(b, Decl(indexedAccessWithFreshObjectLiteral.ts, 10, 11))
|
||||
|
||||
c: false
|
||||
>c : Symbol(c, Decl(indexedAccessWithFreshObjectLiteral.ts, 11, 12))
|
||||
|
||||
}[id]
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 8, 14))
|
||||
}
|
||||
|
||||
function baz (id: '1' | '2') {
|
||||
>baz : Symbol(baz, Decl(indexedAccessWithFreshObjectLiteral.ts, 14, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 16, 14))
|
||||
|
||||
return {
|
||||
1: 1,
|
||||
>1 : Symbol(1, Decl(indexedAccessWithFreshObjectLiteral.ts, 17, 10))
|
||||
|
||||
2: "",
|
||||
>2 : Symbol(2, Decl(indexedAccessWithFreshObjectLiteral.ts, 18, 11))
|
||||
|
||||
3: false
|
||||
>3 : Symbol(3, Decl(indexedAccessWithFreshObjectLiteral.ts, 19, 12))
|
||||
|
||||
}[id]
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 16, 14))
|
||||
}
|
||||
|
||||
function qux (id: 1 | 2) {
|
||||
>qux : Symbol(qux, Decl(indexedAccessWithFreshObjectLiteral.ts, 22, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 24, 14))
|
||||
|
||||
return {
|
||||
1: 1,
|
||||
>1 : Symbol(1, Decl(indexedAccessWithFreshObjectLiteral.ts, 25, 10))
|
||||
|
||||
2: "",
|
||||
>2 : Symbol(2, Decl(indexedAccessWithFreshObjectLiteral.ts, 26, 11))
|
||||
|
||||
3: false
|
||||
>3 : Symbol(3, Decl(indexedAccessWithFreshObjectLiteral.ts, 27, 12))
|
||||
|
||||
}[id]
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 24, 14))
|
||||
}
|
||||
|
||||
function quux (id: 'a' | 'b' | 'z') {
|
||||
>quux : Symbol(quux, Decl(indexedAccessWithFreshObjectLiteral.ts, 30, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 32, 15))
|
||||
|
||||
return {
|
||||
a: 1,
|
||||
>a : Symbol(a, Decl(indexedAccessWithFreshObjectLiteral.ts, 33, 10))
|
||||
|
||||
b: "",
|
||||
>b : Symbol(b, Decl(indexedAccessWithFreshObjectLiteral.ts, 34, 11))
|
||||
|
||||
c: false
|
||||
>c : Symbol(c, Decl(indexedAccessWithFreshObjectLiteral.ts, 35, 12))
|
||||
|
||||
}[id]
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 32, 15))
|
||||
}
|
||||
|
||||
function corge(id: string) {
|
||||
>corge : Symbol(corge, Decl(indexedAccessWithFreshObjectLiteral.ts, 38, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 40, 15))
|
||||
|
||||
return ({
|
||||
a: 123,
|
||||
>a : Symbol(a, Decl(indexedAccessWithFreshObjectLiteral.ts, 41, 11))
|
||||
|
||||
b: ""
|
||||
>b : Symbol(b, Decl(indexedAccessWithFreshObjectLiteral.ts, 42, 13))
|
||||
|
||||
} as Record<string, number | string>)[id]
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 40, 15))
|
||||
}
|
||||
|
||||
function grault(id: string) {
|
||||
>grault : Symbol(grault, Decl(indexedAccessWithFreshObjectLiteral.ts, 45, 1))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 47, 16))
|
||||
|
||||
return ({
|
||||
a: 123,
|
||||
>a : Symbol(a, Decl(indexedAccessWithFreshObjectLiteral.ts, 48, 11))
|
||||
|
||||
b: ""
|
||||
>b : Symbol(b, Decl(indexedAccessWithFreshObjectLiteral.ts, 49, 13))
|
||||
|
||||
} as { [k: string]: string | number})[id]
|
||||
>k : Symbol(k, Decl(indexedAccessWithFreshObjectLiteral.ts, 51, 10))
|
||||
>id : Symbol(id, Decl(indexedAccessWithFreshObjectLiteral.ts, 47, 16))
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
=== tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts ===
|
||||
function foo (id: string) {
|
||||
>foo : (id: string) => string | number | boolean | undefined
|
||||
>id : string
|
||||
|
||||
return {
|
||||
>{ a: 1, b: "", c: true }[id] : string | number | boolean | undefined
|
||||
>{ a: 1, b: "", c: true } : { a: number; b: string; c: boolean; }
|
||||
|
||||
a: 1,
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
b: "",
|
||||
>b : string
|
||||
>"" : ""
|
||||
|
||||
c: true
|
||||
>c : boolean
|
||||
>true : true
|
||||
|
||||
}[id]
|
||||
>id : string
|
||||
}
|
||||
|
||||
function bar (id: 'a' | 'b') {
|
||||
>bar : (id: 'a' | 'b') => string | number
|
||||
>id : "a" | "b"
|
||||
|
||||
return {
|
||||
>{ a: 1, b: "", c: false }[id] : string | number
|
||||
>{ a: 1, b: "", c: false } : { a: number; b: string; c: boolean; }
|
||||
|
||||
a: 1,
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
b: "",
|
||||
>b : string
|
||||
>"" : ""
|
||||
|
||||
c: false
|
||||
>c : boolean
|
||||
>false : false
|
||||
|
||||
}[id]
|
||||
>id : "a" | "b"
|
||||
}
|
||||
|
||||
function baz (id: '1' | '2') {
|
||||
>baz : (id: '1' | '2') => string | number
|
||||
>id : "1" | "2"
|
||||
|
||||
return {
|
||||
>{ 1: 1, 2: "", 3: false }[id] : string | number
|
||||
>{ 1: 1, 2: "", 3: false } : { 1: number; 2: string; 3: boolean; }
|
||||
|
||||
1: 1,
|
||||
>1 : number
|
||||
>1 : 1
|
||||
|
||||
2: "",
|
||||
>2 : string
|
||||
>"" : ""
|
||||
|
||||
3: false
|
||||
>3 : boolean
|
||||
>false : false
|
||||
|
||||
}[id]
|
||||
>id : "1" | "2"
|
||||
}
|
||||
|
||||
function qux (id: 1 | 2) {
|
||||
>qux : (id: 1 | 2) => string | number
|
||||
>id : 1 | 2
|
||||
|
||||
return {
|
||||
>{ 1: 1, 2: "", 3: false }[id] : string | number
|
||||
>{ 1: 1, 2: "", 3: false } : { 1: number; 2: string; 3: boolean; }
|
||||
|
||||
1: 1,
|
||||
>1 : number
|
||||
>1 : 1
|
||||
|
||||
2: "",
|
||||
>2 : string
|
||||
>"" : ""
|
||||
|
||||
3: false
|
||||
>3 : boolean
|
||||
>false : false
|
||||
|
||||
}[id]
|
||||
>id : 1 | 2
|
||||
}
|
||||
|
||||
function quux (id: 'a' | 'b' | 'z') {
|
||||
>quux : (id: 'a' | 'b' | 'z') => string | number | undefined
|
||||
>id : "a" | "b" | "z"
|
||||
|
||||
return {
|
||||
>{ a: 1, b: "", c: false }[id] : string | number | undefined
|
||||
>{ a: 1, b: "", c: false } : { a: number; b: string; c: boolean; }
|
||||
|
||||
a: 1,
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
b: "",
|
||||
>b : string
|
||||
>"" : ""
|
||||
|
||||
c: false
|
||||
>c : boolean
|
||||
>false : false
|
||||
|
||||
}[id]
|
||||
>id : "a" | "b" | "z"
|
||||
}
|
||||
|
||||
function corge(id: string) {
|
||||
>corge : (id: string) => string | number
|
||||
>id : string
|
||||
|
||||
return ({
|
||||
>({ a: 123, b: "" } as Record<string, number | string>)[id] : string | number
|
||||
>({ a: 123, b: "" } as Record<string, number | string>) : Record<string, string | number>
|
||||
>{ a: 123, b: "" } as Record<string, number | string> : Record<string, string | number>
|
||||
>{ a: 123, b: "" } : { a: number; b: string; }
|
||||
|
||||
a: 123,
|
||||
>a : number
|
||||
>123 : 123
|
||||
|
||||
b: ""
|
||||
>b : string
|
||||
>"" : ""
|
||||
|
||||
} as Record<string, number | string>)[id]
|
||||
>id : string
|
||||
}
|
||||
|
||||
function grault(id: string) {
|
||||
>grault : (id: string) => string | number
|
||||
>id : string
|
||||
|
||||
return ({
|
||||
>({ a: 123, b: "" } as { [k: string]: string | number})[id] : string | number
|
||||
>({ a: 123, b: "" } as { [k: string]: string | number}) : { [k: string]: string | number; }
|
||||
>{ a: 123, b: "" } as { [k: string]: string | number} : { [k: string]: string | number; }
|
||||
>{ a: 123, b: "" } : { a: number; b: string; }
|
||||
|
||||
a: 123,
|
||||
>a : number
|
||||
>123 : 123
|
||||
|
||||
b: ""
|
||||
>b : string
|
||||
>"" : ""
|
||||
|
||||
} as { [k: string]: string | number})[id]
|
||||
>k : string
|
||||
>id : string
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
tests/cases/compiler/noImplicitAnyIndexing.ts(12,37): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
|
||||
tests/cases/compiler/noImplicitAnyIndexing.ts(19,9): error TS7053: Element implicitly has an 'any' type because expression of type '"hi"' can't be used to index type '{}'.
|
||||
Property 'hi' does not exist on type '{}'.
|
||||
tests/cases/compiler/noImplicitAnyIndexing.ts(22,9): error TS7053: Element implicitly has an 'any' type because expression of type '10' can't be used to index type '{}'.
|
||||
Property '10' does not exist on type '{}'.
|
||||
tests/cases/compiler/noImplicitAnyIndexing.ts(19,9): error TS2339: Property 'hi' does not exist on type '{}'.
|
||||
tests/cases/compiler/noImplicitAnyIndexing.ts(22,9): error TS2339: Property '10' does not exist on type '{}'.
|
||||
tests/cases/compiler/noImplicitAnyIndexing.ts(30,10): error TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'.
|
||||
|
||||
|
||||
|
@ -29,14 +27,12 @@ tests/cases/compiler/noImplicitAnyIndexing.ts(30,10): error TS7053: Element impl
|
|||
// Should report an implicit 'any'.
|
||||
var x = {}["hi"];
|
||||
~~~~~~~~
|
||||
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"hi"' can't be used to index type '{}'.
|
||||
!!! error TS7053: Property 'hi' does not exist on type '{}'.
|
||||
!!! error TS2339: Property 'hi' does not exist on type '{}'.
|
||||
|
||||
// Should report an implicit 'any'.
|
||||
var y = {}[10];
|
||||
~~~~~~
|
||||
!!! error TS7053: Element implicitly has an 'any' type because expression of type '10' can't be used to index type '{}'.
|
||||
!!! error TS7053: Property '10' does not exist on type '{}'.
|
||||
!!! error TS2339: Property '10' does not exist on type '{}'.
|
||||
|
||||
|
||||
var hi: any = "hi";
|
||||
|
|
|
@ -39,15 +39,15 @@ var strRepresentation4 = MyEmusEnum["emu"];
|
|||
|
||||
// Should report an implicit 'any'.
|
||||
var x = {}["hi"];
|
||||
>x : any
|
||||
>{}["hi"] : any
|
||||
>x : undefined
|
||||
>{}["hi"] : undefined
|
||||
>{} : {}
|
||||
>"hi" : "hi"
|
||||
|
||||
// Should report an implicit 'any'.
|
||||
var y = {}[10];
|
||||
>y : any
|
||||
>{}[10] : any
|
||||
>y : undefined
|
||||
>{}[10] : undefined
|
||||
>{} : {}
|
||||
>10 : 10
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts(19,9): error TS2339: Property 'hi' does not exist on type '{}'.
|
||||
tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts(22,9): error TS2339: Property '10' does not exist on type '{}'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/noImplicitAnyIndexingSuppressed.ts (2 errors) ====
|
||||
enum MyEmusEnum {
|
||||
emu
|
||||
}
|
||||
|
||||
// Should be okay; should be a string.
|
||||
var strRepresentation1 = MyEmusEnum[0]
|
||||
|
||||
// Should be okay; should be a string.
|
||||
var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu]
|
||||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var strRepresentation3 = MyEmusEnum["monehh"];
|
||||
|
||||
// Should be okay; should be a MyEmusEnum
|
||||
var strRepresentation4 = MyEmusEnum["emu"];
|
||||
|
||||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var x = {}["hi"];
|
||||
~~~~~~~~
|
||||
!!! error TS2339: Property 'hi' does not exist on type '{}'.
|
||||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var y = {}[10];
|
||||
~~~~~~
|
||||
!!! error TS2339: Property '10' does not exist on type '{}'.
|
||||
|
||||
var hi: any = "hi";
|
||||
|
||||
var emptyObj = {};
|
||||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var z1 = emptyObj[hi];
|
||||
var z2 = (<any>emptyObj)[hi];
|
||||
|
||||
interface MyMap<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
var m: MyMap<number> = {
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 2,
|
||||
"Okay that's enough for today.": NaN
|
||||
};
|
||||
|
||||
var mResult1 = m[MyEmusEnum.emu];
|
||||
var mResult2 = m[MyEmusEnum[MyEmusEnum.emu]];
|
||||
var mResult3 = m[hi];
|
||||
|
||||
|
|
@ -24,8 +24,8 @@ var strRepresentation2 = MyEmusEnum[MyEmusEnum.emu]
|
|||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var strRepresentation3 = MyEmusEnum["monehh"];
|
||||
>strRepresentation3 : error
|
||||
>MyEmusEnum["monehh"] : error
|
||||
>strRepresentation3 : any
|
||||
>MyEmusEnum["monehh"] : any
|
||||
>MyEmusEnum : typeof MyEmusEnum
|
||||
>"monehh" : "monehh"
|
||||
|
||||
|
@ -39,15 +39,15 @@ var strRepresentation4 = MyEmusEnum["emu"];
|
|||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var x = {}["hi"];
|
||||
>x : error
|
||||
>{}["hi"] : error
|
||||
>x : undefined
|
||||
>{}["hi"] : undefined
|
||||
>{} : {}
|
||||
>"hi" : "hi"
|
||||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var y = {}[10];
|
||||
>y : error
|
||||
>{}[10] : error
|
||||
>y : undefined
|
||||
>{}[10] : undefined
|
||||
>{} : {}
|
||||
>10 : 10
|
||||
|
||||
|
@ -61,8 +61,8 @@ var emptyObj = {};
|
|||
|
||||
// Should be okay, as we suppress implicit 'any' property access checks
|
||||
var z1 = emptyObj[hi];
|
||||
>z1 : error
|
||||
>emptyObj[hi] : error
|
||||
>z1 : any
|
||||
>emptyObj[hi] : any
|
||||
>emptyObj : {}
|
||||
>hi : any
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
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(1,9): error TS2339: 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 '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; }'.
|
||||
|
@ -16,11 +15,11 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(42,3): error TS7052:
|
|||
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(49,3): error TS2339: Property 'hello' does not exist on type '{ get: (key: string) => string; set: (key: string, value: string) => void; }'.
|
||||
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(56,3): error TS2339: Property 'hello' does not exist on type '{ get: (key: string) => string; set: (key: string, value: string) => void; }'.
|
||||
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'?
|
||||
|
@ -41,8 +40,7 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(99,1): error TS7052:
|
|||
==== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts (31 errors) ====
|
||||
var a = {}["hello"];
|
||||
~~~~~~~~~~~
|
||||
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{}'.
|
||||
!!! error TS7053: Property 'hello' does not exist on type '{}'.
|
||||
!!! error TS2339: Property 'hello' does not exist on type '{}'.
|
||||
var b: string = { '': 'foo' }[''];
|
||||
|
||||
var c = {
|
||||
|
@ -123,7 +121,7 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(99,1): error TS7052:
|
|||
{
|
||||
({ 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'?
|
||||
!!! error TS2339: Property 'hello' does not exist on type '{ get: (key: string) => string; set: (key: string, value: string) => void; }'.
|
||||
({ 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'?
|
||||
|
@ -138,7 +136,7 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(99,1): error TS7052:
|
|||
{
|
||||
({ 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'?
|
||||
!!! error TS2339: Property 'hello' does not exist on type '{ get: (key: string) => string; set: (key: string, value: string) => void; }'.
|
||||
({ 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'?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
=== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts ===
|
||||
var a = {}["hello"];
|
||||
>a : any
|
||||
>{}["hello"] : any
|
||||
>a : undefined
|
||||
>{}["hello"] : undefined
|
||||
>{} : {}
|
||||
>"hello" : "hello"
|
||||
|
||||
|
@ -188,7 +188,7 @@ const bar = d['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) => {} })['hello'] : undefined
|
||||
>({ 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
|
||||
|
@ -251,7 +251,7 @@ const bar = d['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['hello'] : undefined
|
||||
>({ 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; }; }
|
||||
|
|
55
tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts
Normal file
55
tests/cases/compiler/indexedAccessWithFreshObjectLiteral.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
// @strict: true
|
||||
|
||||
function foo (id: string) {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: true
|
||||
}[id]
|
||||
}
|
||||
|
||||
function bar (id: 'a' | 'b') {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function baz (id: '1' | '2') {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function qux (id: 1 | 2) {
|
||||
return {
|
||||
1: 1,
|
||||
2: "",
|
||||
3: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function quux (id: 'a' | 'b' | 'z') {
|
||||
return {
|
||||
a: 1,
|
||||
b: "",
|
||||
c: false
|
||||
}[id]
|
||||
}
|
||||
|
||||
function corge(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as Record<string, number | string>)[id]
|
||||
}
|
||||
|
||||
function grault(id: string) {
|
||||
return ({
|
||||
a: 123,
|
||||
b: ""
|
||||
} as { [k: string]: string | number})[id]
|
||||
}
|
Loading…
Reference in a new issue