Merge pull request #14222 from Microsoft/addAnyStringIndexerToJSObjects
Add a string indexer to any for object literals on a .js file
This commit is contained in:
commit
b3161e365a
|
@ -244,6 +244,7 @@ namespace ts {
|
||||||
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||||
|
|
||||||
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
|
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
|
||||||
|
const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
|
||||||
|
|
||||||
const globals = createMap<Symbol>();
|
const globals = createMap<Symbol>();
|
||||||
/**
|
/**
|
||||||
|
@ -12252,6 +12253,7 @@ namespace ts {
|
||||||
const contextualType = getApparentTypeOfContextualType(node);
|
const contextualType = getApparentTypeOfContextualType(node);
|
||||||
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
||||||
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
|
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
|
||||||
|
const isJSObjectLiteral = !contextualType && isInJavaScriptFile(node);
|
||||||
let typeFlags: TypeFlags = 0;
|
let typeFlags: TypeFlags = 0;
|
||||||
let patternWithComputedProperties = false;
|
let patternWithComputedProperties = false;
|
||||||
let hasComputedStringProperty = false;
|
let hasComputedStringProperty = false;
|
||||||
|
@ -12389,8 +12391,8 @@ namespace ts {
|
||||||
return createObjectLiteralType();
|
return createObjectLiteralType();
|
||||||
|
|
||||||
function createObjectLiteralType() {
|
function createObjectLiteralType() {
|
||||||
const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.String) : undefined;
|
const stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.String) : undefined;
|
||||||
const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.Number) : undefined;
|
const numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.Number) : undefined;
|
||||||
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||||
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
|
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
|
||||||
result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
|
result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
=== tests/cases/compiler/a.js ===
|
=== tests/cases/compiler/a.js ===
|
||||||
|
|
||||||
function foo() {
|
function foo() {
|
||||||
>foo : () => { a: number; b: string; }
|
>foo : () => { [x: string]: any; a: number; b: string; }
|
||||||
|
|
||||||
var a = 10;
|
var a = 10;
|
||||||
>a : number
|
>a : number
|
||||||
|
@ -12,7 +12,7 @@ function foo() {
|
||||||
>"Hello" : "Hello"
|
>"Hello" : "Hello"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
>{ a, b } : { a: number; b: string; }
|
>{ a, b } : { [x: string]: any; a: number; b: string; }
|
||||||
|
|
||||||
a,
|
a,
|
||||||
>a : number
|
>a : number
|
||||||
|
|
63
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js
Normal file
63
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//// [tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts] ////
|
||||||
|
|
||||||
|
//// [a.js]
|
||||||
|
|
||||||
|
var variable = {};
|
||||||
|
variable.a = 0;
|
||||||
|
|
||||||
|
class C {
|
||||||
|
initializedMember = {};
|
||||||
|
constructor() {
|
||||||
|
this.member = {};
|
||||||
|
this.member.a = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
property: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.property.a = 0;
|
||||||
|
|
||||||
|
var arr = [{}];
|
||||||
|
|
||||||
|
function getObj() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// [b.ts]
|
||||||
|
variable.a = 1;
|
||||||
|
(new C()).member.a = 1;
|
||||||
|
(new C()).initializedMember.a = 1;
|
||||||
|
obj.property.a = 1;
|
||||||
|
arr[0].a = 1;
|
||||||
|
getObj().a = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//// [output.js]
|
||||||
|
var variable = {};
|
||||||
|
variable.a = 0;
|
||||||
|
var C = (function () {
|
||||||
|
function C() {
|
||||||
|
this.initializedMember = {};
|
||||||
|
this.member = {};
|
||||||
|
this.member.a = 0;
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}());
|
||||||
|
var obj = {
|
||||||
|
property: {}
|
||||||
|
};
|
||||||
|
obj.property.a = 0;
|
||||||
|
var arr = [{}];
|
||||||
|
function getObj() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
variable.a = 1;
|
||||||
|
(new C()).member.a = 1;
|
||||||
|
(new C()).initializedMember.a = 1;
|
||||||
|
obj.property.a = 1;
|
||||||
|
arr[0].a = 1;
|
||||||
|
getObj().a = 1;
|
76
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols
Normal file
76
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
=== tests/cases/conformance/salsa/a.js ===
|
||||||
|
|
||||||
|
var variable = {};
|
||||||
|
>variable : Symbol(variable, Decl(a.js, 1, 3))
|
||||||
|
|
||||||
|
variable.a = 0;
|
||||||
|
>variable : Symbol(variable, Decl(a.js, 1, 3))
|
||||||
|
|
||||||
|
class C {
|
||||||
|
>C : Symbol(C, Decl(a.js, 2, 15))
|
||||||
|
|
||||||
|
initializedMember = {};
|
||||||
|
>initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9))
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.member = {};
|
||||||
|
>this.member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
>this : Symbol(C, Decl(a.js, 2, 15))
|
||||||
|
>member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
|
||||||
|
this.member.a = 0;
|
||||||
|
>this.member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
>this : Symbol(C, Decl(a.js, 2, 15))
|
||||||
|
>member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
>obj : Symbol(obj, Decl(a.js, 12, 3))
|
||||||
|
|
||||||
|
property: {}
|
||||||
|
>property : Symbol(property, Decl(a.js, 12, 11))
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.property.a = 0;
|
||||||
|
>obj.property : Symbol(property, Decl(a.js, 12, 11))
|
||||||
|
>obj : Symbol(obj, Decl(a.js, 12, 3))
|
||||||
|
>property : Symbol(property, Decl(a.js, 12, 11))
|
||||||
|
|
||||||
|
var arr = [{}];
|
||||||
|
>arr : Symbol(arr, Decl(a.js, 18, 3))
|
||||||
|
|
||||||
|
function getObj() {
|
||||||
|
>getObj : Symbol(getObj, Decl(a.js, 18, 15))
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
=== tests/cases/conformance/salsa/b.ts ===
|
||||||
|
variable.a = 1;
|
||||||
|
>variable : Symbol(variable, Decl(a.js, 1, 3))
|
||||||
|
|
||||||
|
(new C()).member.a = 1;
|
||||||
|
>(new C()).member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
>C : Symbol(C, Decl(a.js, 2, 15))
|
||||||
|
>member : Symbol(C.member, Decl(a.js, 6, 19))
|
||||||
|
|
||||||
|
(new C()).initializedMember.a = 1;
|
||||||
|
>(new C()).initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9))
|
||||||
|
>C : Symbol(C, Decl(a.js, 2, 15))
|
||||||
|
>initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9))
|
||||||
|
|
||||||
|
obj.property.a = 1;
|
||||||
|
>obj.property : Symbol(property, Decl(a.js, 12, 11))
|
||||||
|
>obj : Symbol(obj, Decl(a.js, 12, 3))
|
||||||
|
>property : Symbol(property, Decl(a.js, 12, 11))
|
||||||
|
|
||||||
|
arr[0].a = 1;
|
||||||
|
>arr : Symbol(arr, Decl(a.js, 18, 3))
|
||||||
|
|
||||||
|
getObj().a = 1;
|
||||||
|
>getObj : Symbol(getObj, Decl(a.js, 18, 15))
|
||||||
|
|
||||||
|
|
128
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types
Normal file
128
tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
=== tests/cases/conformance/salsa/a.js ===
|
||||||
|
|
||||||
|
var variable = {};
|
||||||
|
>variable : { [x: string]: any; }
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
|
||||||
|
variable.a = 0;
|
||||||
|
>variable.a = 0 : 0
|
||||||
|
>variable.a : any
|
||||||
|
>variable : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>0 : 0
|
||||||
|
|
||||||
|
class C {
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
initializedMember = {};
|
||||||
|
>initializedMember : { [x: string]: any; }
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.member = {};
|
||||||
|
>this.member = {} : { [x: string]: any; }
|
||||||
|
>this.member : { [x: string]: any; }
|
||||||
|
>this : this
|
||||||
|
>member : { [x: string]: any; }
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
|
||||||
|
this.member.a = 0;
|
||||||
|
>this.member.a = 0 : 0
|
||||||
|
>this.member.a : any
|
||||||
|
>this.member : { [x: string]: any; }
|
||||||
|
>this : this
|
||||||
|
>member : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>0 : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
>obj : { [x: string]: any; property: { [x: string]: any; }; }
|
||||||
|
>{ property: {}} : { [x: string]: any; property: { [x: string]: any; }; }
|
||||||
|
|
||||||
|
property: {}
|
||||||
|
>property : { [x: string]: any; }
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.property.a = 0;
|
||||||
|
>obj.property.a = 0 : 0
|
||||||
|
>obj.property.a : any
|
||||||
|
>obj.property : { [x: string]: any; }
|
||||||
|
>obj : { [x: string]: any; property: { [x: string]: any; }; }
|
||||||
|
>property : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>0 : 0
|
||||||
|
|
||||||
|
var arr = [{}];
|
||||||
|
>arr : { [x: string]: any; }[]
|
||||||
|
>[{}] : { [x: string]: any; }[]
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
|
||||||
|
function getObj() {
|
||||||
|
>getObj : () => { [x: string]: any; }
|
||||||
|
|
||||||
|
return {};
|
||||||
|
>{} : { [x: string]: any; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
=== tests/cases/conformance/salsa/b.ts ===
|
||||||
|
variable.a = 1;
|
||||||
|
>variable.a = 1 : 1
|
||||||
|
>variable.a : any
|
||||||
|
>variable : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
(new C()).member.a = 1;
|
||||||
|
>(new C()).member.a = 1 : 1
|
||||||
|
>(new C()).member.a : any
|
||||||
|
>(new C()).member : { [x: string]: any; }
|
||||||
|
>(new C()) : C
|
||||||
|
>new C() : C
|
||||||
|
>C : typeof C
|
||||||
|
>member : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
(new C()).initializedMember.a = 1;
|
||||||
|
>(new C()).initializedMember.a = 1 : 1
|
||||||
|
>(new C()).initializedMember.a : any
|
||||||
|
>(new C()).initializedMember : { [x: string]: any; }
|
||||||
|
>(new C()) : C
|
||||||
|
>new C() : C
|
||||||
|
>C : typeof C
|
||||||
|
>initializedMember : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
obj.property.a = 1;
|
||||||
|
>obj.property.a = 1 : 1
|
||||||
|
>obj.property.a : any
|
||||||
|
>obj.property : { [x: string]: any; }
|
||||||
|
>obj : { [x: string]: any; property: { [x: string]: any; }; }
|
||||||
|
>property : { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
arr[0].a = 1;
|
||||||
|
>arr[0].a = 1 : 1
|
||||||
|
>arr[0].a : any
|
||||||
|
>arr[0] : { [x: string]: any; }
|
||||||
|
>arr : { [x: string]: any; }[]
|
||||||
|
>0 : 0
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
getObj().a = 1;
|
||||||
|
>getObj().a = 1 : 1
|
||||||
|
>getObj().a : any
|
||||||
|
>getObj() : { [x: string]: any; }
|
||||||
|
>getObj : () => { [x: string]: any; }
|
||||||
|
>a : any
|
||||||
|
>1 : 1
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
=== /a.ts ===
|
=== /a.ts ===
|
||||||
import foo from "foo";
|
import foo from "foo";
|
||||||
>foo : { bar(): number; }
|
>foo : { [x: string]: any; bar(): number; }
|
||||||
|
|
||||||
foo.bar();
|
foo.bar();
|
||||||
>foo.bar() : number
|
>foo.bar() : number
|
||||||
>foo.bar : () => number
|
>foo.bar : () => number
|
||||||
>foo : { bar(): number; }
|
>foo : { [x: string]: any; bar(): number; }
|
||||||
>bar : () => number
|
>bar : () => number
|
||||||
|
|
||||||
=== /node_modules/foo/index.js ===
|
=== /node_modules/foo/index.js ===
|
||||||
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
// Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed.
|
||||||
|
|
||||||
exports.default = { bar() { return 0; } }
|
exports.default = { bar() { return 0; } }
|
||||||
>exports.default = { bar() { return 0; } } : { bar(): number; }
|
>exports.default = { bar() { return 0; } } : { [x: string]: any; bar(): number; }
|
||||||
>exports.default : any
|
>exports.default : any
|
||||||
>exports : any
|
>exports : any
|
||||||
>default : any
|
>default : any
|
||||||
>{ bar() { return 0; } } : { bar(): number; }
|
>{ bar() { return 0; } } : { [x: string]: any; bar(): number; }
|
||||||
>bar : () => number
|
>bar : () => number
|
||||||
>0 : 0
|
>0 : 0
|
||||||
|
|
||||||
|
|
36
tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts
Normal file
36
tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// @out: output.js
|
||||||
|
// @allowJs: true
|
||||||
|
|
||||||
|
// @filename: a.js
|
||||||
|
var variable = {};
|
||||||
|
variable.a = 0;
|
||||||
|
|
||||||
|
class C {
|
||||||
|
initializedMember = {};
|
||||||
|
constructor() {
|
||||||
|
this.member = {};
|
||||||
|
this.member.a = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
property: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.property.a = 0;
|
||||||
|
|
||||||
|
var arr = [{}];
|
||||||
|
|
||||||
|
function getObj() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @filename: b.ts
|
||||||
|
variable.a = 1;
|
||||||
|
(new C()).member.a = 1;
|
||||||
|
(new C()).initializedMember.a = 1;
|
||||||
|
obj.property.a = 1;
|
||||||
|
arr[0].a = 1;
|
||||||
|
getObj().a = 1;
|
||||||
|
|
Loading…
Reference in a new issue