@@ -66,8 +66,8 @@ module ts {
66
66
var numberType = createIntrinsicType(TypeFlags.Number, "number");
67
67
var booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
68
68
var voidType = createIntrinsicType(TypeFlags.Void, "void");
69
- var undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.Unwidened , "undefined");
70
- var nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.Unwidened , "null");
69
+ var undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull , "undefined");
70
+ var nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull , "null");
71
71
var unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
72
72
var resolvingType = createIntrinsicType(TypeFlags.Any, "__resolving__");
73
73
@@ -2826,15 +2826,22 @@ module ts {
2826
2826
}
2827
2827
}
2828
2828
2829
- function getUnwidenedFlagOfTypes(types: Type[]): TypeFlags {
2830
- return forEach(types, t => t.flags & TypeFlags.Unwidened) || 0;
2829
+ // This function is used to propagate widening flags when creating new object types references and union types.
2830
+ // It is only necessary to do so if a constituent type might be the undefined type, the null type, or the type
2831
+ // of an object literal (since those types have widening related information we need to track).
2832
+ function getWideningFlagsOfTypes(types: Type[]): TypeFlags {
2833
+ var result: TypeFlags = 0;
2834
+ for (var i = 0; i < types.length; i++) {
2835
+ result |= types[i].flags;
2836
+ }
2837
+ return result & TypeFlags.RequiresWidening;
2831
2838
}
2832
2839
2833
2840
function createTypeReference(target: GenericType, typeArguments: Type[]): TypeReference {
2834
2841
var id = getTypeListId(typeArguments);
2835
2842
var type = target.instantiations[id];
2836
2843
if (!type) {
2837
- var flags = TypeFlags.Reference | getUnwidenedFlagOfTypes (typeArguments);
2844
+ var flags = TypeFlags.Reference | getWideningFlagsOfTypes (typeArguments);
2838
2845
type = target.instantiations[id] = <TypeReference>createObjectType(flags, target.symbol);
2839
2846
type.target = target;
2840
2847
type.typeArguments = typeArguments;
@@ -3095,7 +3102,7 @@ module ts {
3095
3102
var id = getTypeListId(sortedTypes);
3096
3103
var type = unionTypes[id];
3097
3104
if (!type) {
3098
- type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getUnwidenedFlagOfTypes (sortedTypes));
3105
+ type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes (sortedTypes));
3099
3106
type.types = sortedTypes;
3100
3107
}
3101
3108
return type;
@@ -3711,12 +3718,13 @@ module ts {
3711
3718
}
3712
3719
var result = Ternary.True;
3713
3720
var properties = getPropertiesOfObjectType(target);
3721
+ var requireOptionalProperties = relation === subtypeRelation && !(source.flags & TypeFlags.ObjectLiteral);
3714
3722
for (var i = 0; i < properties.length; i++) {
3715
3723
var targetProp = properties[i];
3716
3724
var sourceProp = getPropertyOfType(source, targetProp.name);
3717
3725
if (sourceProp !== targetProp) {
3718
3726
if (!sourceProp) {
3719
- if (relation === subtypeRelation || !(targetProp.flags & SymbolFlags.Optional)) {
3727
+ if (!(targetProp.flags & SymbolFlags.Optional) || requireOptionalProperties ) {
3720
3728
if (reportErrors) {
3721
3729
reportError(Diagnostics.Property_0_is_missing_in_type_1, symbolToString(targetProp), typeToString(source));
3722
3730
}
@@ -4107,10 +4115,6 @@ module ts {
4107
4115
errorMessageChainHead);
4108
4116
}
4109
4117
4110
- function isTypeOfObjectLiteral(type: Type): boolean {
4111
- return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
4112
- }
4113
-
4114
4118
function isArrayType(type: Type): boolean {
4115
4119
return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
4116
4120
}
@@ -4123,13 +4127,18 @@ module ts {
4123
4127
var properties = getPropertiesOfObjectType(type);
4124
4128
var members: SymbolTable = {};
4125
4129
forEach(properties, p => {
4126
- var symbol = <TransientSymbol>createSymbol(p.flags | SymbolFlags.Transient, p.name);
4127
- symbol.declarations = p.declarations;
4128
- symbol.parent = p.parent;
4129
- symbol.type = getWidenedType(getTypeOfSymbol(p));
4130
- symbol.target = p;
4131
- if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
4132
- members[symbol.name] = symbol;
4130
+ var propType = getTypeOfSymbol(p);
4131
+ var widenedType = getWidenedType(propType);
4132
+ if (propType !== widenedType) {
4133
+ var symbol = <TransientSymbol>createSymbol(p.flags | SymbolFlags.Transient, p.name);
4134
+ symbol.declarations = p.declarations;
4135
+ symbol.parent = p.parent;
4136
+ symbol.type = widenedType;
4137
+ symbol.target = p;
4138
+ if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
4139
+ p = symbol;
4140
+ }
4141
+ members[p.name] = p;
4133
4142
});
4134
4143
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
4135
4144
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
@@ -4139,16 +4148,16 @@ module ts {
4139
4148
}
4140
4149
4141
4150
function getWidenedType(type: Type): Type {
4142
- if (type.flags & TypeFlags.Unwidened ) {
4151
+ if (type.flags & TypeFlags.RequiresWidening ) {
4143
4152
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
4144
4153
return anyType;
4145
4154
}
4155
+ if (type.flags & TypeFlags.ObjectLiteral) {
4156
+ return getWidenedTypeOfObjectLiteral(type);
4157
+ }
4146
4158
if (type.flags & TypeFlags.Union) {
4147
4159
return getUnionType(map((<UnionType>type).types, getWidenedType));
4148
4160
}
4149
- if (isTypeOfObjectLiteral(type)) {
4150
- return getWidenedTypeOfObjectLiteral(type);
4151
- }
4152
4161
if (isArrayType(type)) {
4153
4162
return createArrayType(getWidenedType((<TypeReference>type).typeArguments[0]));
4154
4163
}
@@ -4169,11 +4178,11 @@ module ts {
4169
4178
if (isArrayType(type)) {
4170
4179
return reportWideningErrorsInType((<TypeReference>type).typeArguments[0]);
4171
4180
}
4172
- if (isTypeOfObjectLiteral( type) ) {
4181
+ if (type.flags & TypeFlags.ObjectLiteral ) {
4173
4182
var errorReported = false;
4174
4183
forEach(getPropertiesOfObjectType(type), p => {
4175
4184
var t = getTypeOfSymbol(p);
4176
- if (t.flags & TypeFlags.Unwidened ) {
4185
+ if (t.flags & TypeFlags.ContainsUndefinedOrNull ) {
4177
4186
if (!reportWideningErrorsInType(t)) {
4178
4187
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
4179
4188
}
@@ -4217,7 +4226,7 @@ module ts {
4217
4226
}
4218
4227
4219
4228
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
4220
- if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.Unwidened ) {
4229
+ if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull ) {
4221
4230
// Report implicit any error within type if possible, otherwise report error on declaration
4222
4231
if (!reportWideningErrorsInType(type)) {
4223
4232
reportImplicitAnyError(declaration, type);
@@ -5492,21 +5501,10 @@ module ts {
5492
5501
propertiesArray.push(member);
5493
5502
}
5494
5503
5495
- // If object literal is contextually (but not inferentially) typed, copy missing optional properties from
5496
- // the contextual type such that the resulting type becomes a subtype in cases where only optional properties
5497
- // were omitted. There is no need to create new property objects as nothing in them needs to change.
5498
- if (contextualType && !isInferentialContext(contextualMapper)) {
5499
- forEach(getPropertiesOfObjectType(contextualType), p => {
5500
- if (p.flags & SymbolFlags.Optional && !hasProperty(propertiesTable, p.name)) {
5501
- propertiesTable[p.name] = p;
5502
- }
5503
- });
5504
- }
5505
-
5506
5504
var stringIndexType = getIndexType(IndexKind.String);
5507
5505
var numberIndexType = getIndexType(IndexKind.Number);
5508
5506
var result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
5509
- result.flags |= (typeFlags & TypeFlags.Unwidened );
5507
+ result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull );
5510
5508
return result;
5511
5509
5512
5510
function getIndexType(kind: IndexKind) {
@@ -5525,7 +5523,9 @@ module ts {
5525
5523
}
5526
5524
}
5527
5525
}
5528
- return propTypes.length ? getUnionType(propTypes) : undefinedType;
5526
+ var result = propTypes.length ? getUnionType(propTypes) : undefinedType;
5527
+ typeFlags |= result.flags;
5528
+ return result;
5529
5529
}
5530
5530
return undefined;
5531
5531
}
0 commit comments