@@ -1966,15 +1966,12 @@ namespace ts {
19661966 }
19671967
19681968 return _displayBuilder || (_displayBuilder = {
1969- symbolToString: symbolToString,
1970- typeToString: typeToString,
19711969 buildSymbolDisplay: buildSymbolDisplay,
19721970 buildTypeDisplay: buildTypeDisplay,
19731971 buildTypeParameterDisplay: buildTypeParameterDisplay,
19741972 buildParameterDisplay: buildParameterDisplay,
19751973 buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
19761974 buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
1977- buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
19781975 buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
19791976 buildSignatureDisplay: buildSignatureDisplay,
19801977 buildReturnTypeDisplay: buildReturnTypeDisplay
@@ -4480,6 +4477,16 @@ namespace ts {
44804477 errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
44814478 }
44824479
4480+ function reportRelationError(message: DiagnosticMessage, source: Type, target: Type) {
4481+ let sourceType = typeToString(source);
4482+ let targetType = typeToString(target);
4483+ if (sourceType === targetType) {
4484+ sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
4485+ targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
4486+ }
4487+ reportError(message || Diagnostics.Type_0_is_not_assignable_to_type_1, sourceType, targetType);
4488+ }
4489+
44834490 // Compare two types and return
44844491 // Ternary.True if they are related with no assumptions,
44854492 // Ternary.Maybe if they are related with assumptions of other relationships, or
@@ -4499,7 +4506,19 @@ namespace ts {
44994506 if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
45004507 }
45014508 }
4509+
4510+ if (relation === assignableRelation && source.flags & TypeFlags.ObjectLiteral && source.flags & TypeFlags.FreshObjectLiteral) {
4511+ if (hasExcessProperties(<ObjectType>source, target, reportErrors)) {
4512+ if (reportErrors) {
4513+ reportRelationError(headMessage, source, target);
4514+ }
4515+ return Ternary.False;
4516+ }
4517+ source = getRegularTypeOfObjectLiteral(source);
4518+ }
4519+
45024520 let saveErrorInfo = errorInfo;
4521+
45034522 if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
45044523 // We have type references to same target type, see if relationship holds for all type arguments
45054524 if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
@@ -4576,18 +4595,28 @@ namespace ts {
45764595 }
45774596
45784597 if (reportErrors) {
4579- headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
4580- let sourceType = typeToString(source);
4581- let targetType = typeToString(target);
4582- if (sourceType === targetType) {
4583- sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
4584- targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
4585- }
4586- reportError(headMessage, sourceType, targetType);
4598+ reportRelationError(headMessage, source, target);
45874599 }
45884600 return Ternary.False;
45894601 }
45904602
4603+ function hasExcessProperties(source: ObjectType, target: Type, reportErrors: boolean): boolean {
4604+ if (target.flags & TypeFlags.ObjectType) {
4605+ var resolved = resolveStructuredTypeMembers(target);
4606+ if (resolved.properties.length > 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
4607+ for (let prop of getPropertiesOfObjectType(source)) {
4608+ if (!getPropertyOfType(target, prop.name)) {
4609+ if (reportErrors) {
4610+ reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target));
4611+ }
4612+ return true;
4613+ }
4614+ }
4615+ }
4616+ }
4617+ return false;
4618+ }
4619+
45914620 function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
45924621 let result = Ternary.True;
45934622 let sourceTypes = source.types;
@@ -5255,6 +5284,24 @@ namespace ts {
52555284 return (type.flags & TypeFlags.Tuple) && !!(<TupleType>type).elementTypes;
52565285 }
52575286
5287+ function getRegularTypeOfObjectLiteral(type: Type): Type {
5288+ if (type.flags & TypeFlags.FreshObjectLiteral) {
5289+ let regularType = (<FreshObjectLiteralType>type).regularType;
5290+ if (!regularType) {
5291+ regularType = <ResolvedType>createType((<ResolvedType>type).flags & ~TypeFlags.FreshObjectLiteral);
5292+ regularType.symbol = (<ResolvedType>type).symbol;
5293+ regularType.members = (<ResolvedType>type).members;
5294+ regularType.properties = (<ResolvedType>type).properties;
5295+ regularType.callSignatures = (<ResolvedType>type).callSignatures;
5296+ regularType.constructSignatures = (<ResolvedType>type).constructSignatures;
5297+ regularType.stringIndexType = (<ResolvedType>type).stringIndexType;
5298+ regularType.numberIndexType = (<ResolvedType>type).numberIndexType;
5299+ }
5300+ return regularType;
5301+ }
5302+ return type;
5303+ }
5304+
52585305 function getWidenedTypeOfObjectLiteral(type: Type): Type {
52595306 let properties = getPropertiesOfObjectType(type);
52605307 let members: SymbolTable = {};
@@ -6830,18 +6877,6 @@ namespace ts {
68306877 return links.resolvedType;
68316878 }
68326879
6833- function isPermittedProperty(contextualType: Type, propName: string): boolean {
6834- if (contextualType.flags & TypeFlags.ObjectType) {
6835- let resolved = resolveStructuredTypeMembers(<ObjectType>contextualType);
6836- return !!(resolved.properties.length === 0 || resolved.stringIndexType ||
6837- resolved.numberIndexType || getPropertyOfObjectType(contextualType, propName));
6838- }
6839- if (contextualType.flags & TypeFlags.UnionOrIntersection) {
6840- return !forEach((<UnionOrIntersectionType>contextualType).types, type => !isPermittedProperty(type, propName));
6841- }
6842- return true;
6843- }
6844-
68456880 function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type {
68466881 // Grammar checking
68476882 checkGrammarObjectLiteralExpression(node);
@@ -6891,17 +6926,14 @@ namespace ts {
68916926
68926927 if (!hasDynamicName(memberDecl)) {
68936928 propertiesTable[member.name] = member;
6894- if (contextualType && !isPermittedProperty(contextualType, member.name)) {
6895- error(memberDecl.name, Diagnostics.Property_0_does_not_exist_in_contextual_type_1, member.name, typeToString(contextualType));
6896- }
68976929 }
68986930 propertiesArray.push(member);
68996931 }
69006932
69016933 let stringIndexType = getIndexType(IndexKind.String);
69026934 let numberIndexType = getIndexType(IndexKind.Number);
69036935 let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
6904- result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
6936+ result.flags |= TypeFlags.ObjectLiteral | TypeFlags.FreshObjectLiteral | TypeFlags. ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
69056937 return result;
69066938
69076939 function getIndexType(kind: IndexKind) {
@@ -8782,7 +8814,7 @@ namespace ts {
87828814 }
87838815
87848816 function checkAssertion(node: AssertionExpression) {
8785- let exprType = checkExpression(node.expression);
8817+ let exprType = getRegularTypeOfObjectLiteral( checkExpression(node.expression) );
87868818 let targetType = getTypeFromTypeNode(node.type);
87878819 if (produceDiagnostics && targetType !== unknownType) {
87888820 let widenedType = getWidenedType(exprType);
@@ -9559,7 +9591,7 @@ namespace ts {
95599591 return getUnionType([leftType, rightType]);
95609592 case SyntaxKind.EqualsToken:
95619593 checkAssignmentOperator(rightType);
9562- return rightType;
9594+ return getRegularTypeOfObjectLiteral( rightType) ;
95639595 case SyntaxKind.CommaToken:
95649596 return rightType;
95659597 }
0 commit comments