Use transient symbols when computing the indexers for object literals

This commit is contained in:
Jason Freeman 2015-01-26 16:48:53 -08:00
parent 17b19bf465
commit ca8c446d3f
4 changed files with 50 additions and 7 deletions

View file

@ -5441,7 +5441,8 @@ module ts {
// Grammar checking
checkGrammarObjectLiteralExpression(node);
var properties: SymbolTable = {};
var propertiesTable: SymbolTable = {};
var propertiesArray: Symbol[] = [];
var contextualType = getContextualType(node);
var typeFlags: TypeFlags;
@ -5486,8 +5487,9 @@ module ts {
}
if (!hasDynamicName(memberDecl)) {
properties[member.name] = member;
propertiesTable[member.name] = member;
}
propertiesArray.push(member);
}
// If object literal is contextually (but not inferentially) typed, copy missing optional properties from
@ -5495,25 +5497,29 @@ module ts {
// were omitted. There is no need to create new property objects as nothing in them needs to change.
if (contextualType && !isInferentialContext(contextualMapper)) {
forEach(getPropertiesOfObjectType(contextualType), p => {
if (p.flags & SymbolFlags.Optional && !hasProperty(properties, p.name)) {
properties[p.name] = p;
if (p.flags & SymbolFlags.Optional && !hasProperty(propertiesTable, p.name)) {
propertiesTable[p.name] = p;
}
});
}
var stringIndexType = getIndexType(IndexKind.String);
var numberIndexType = getIndexType(IndexKind.Number);
var result = createAnonymousType(node.symbol, properties, emptyArray, emptyArray, stringIndexType, numberIndexType);
var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
result.flags |= (typeFlags & TypeFlags.Unwidened);
return result;
function getIndexType(kind: IndexKind) {
if (contextualType && contextualTypeHasIndexSignature(contextualType, kind)) {
var propTypes: Type[] = [];
for (var i = 0; i < node.properties.length; i++) {
for (var i = 0; i < propertiesArray.length; i++) {
var propertyDecl = node.properties[i];
if (kind === IndexKind.String || isNumericName(propertyDecl.name)) {
var type = getTypeOfSymbol(getSymbolOfNode(propertyDecl));
// Do not call getSymbolOfNode(propertyDecl), as that will get the
// original symbol for the node. We actually want to get the symbol
// created by checkObjectLiteral, since that will be appropriately
// contextually typed and resolved.
var type = getTypeOfSymbol(propertiesArray[i]);
if (!contains(propTypes, type)) {
propTypes.push(type);
}

View file

@ -0,0 +1,13 @@
//// [objectLiteralIndexerNoImplicitAny.ts]
interface I {
[s: string]: any;
}
var x: I = {
p: null
}
//// [objectLiteralIndexerNoImplicitAny.js]
var x = {
p: null
};

View file

@ -0,0 +1,16 @@
=== tests/cases/compiler/objectLiteralIndexerNoImplicitAny.ts ===
interface I {
>I : I
[s: string]: any;
>s : string
}
var x: I = {
>x : I
>I : I
>{ p: null} : { [x: string]: null; p: null; }
p: null
>p : null
}

View file

@ -0,0 +1,8 @@
//@noImplicitAny: true
interface I {
[s: string]: any;
}
var x: I = {
p: null
}