Skip to content

Commit 6fee404

Browse files
committed
Merge pull request #602 from Microsoft/noImplicitAnyOnCast
Do not show noImplictAny errors when widening for a cast expression
2 parents 6534181 + 4f21fb5 commit 6fee404

File tree

4 files changed

+113
-50
lines changed

4 files changed

+113
-50
lines changed

src/compiler/checker.ts

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3132,45 +3132,6 @@ module ts {
31323132
return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
31333133
}
31343134

3135-
function getWidenedTypeOfObjectLiteral(type: Type): Type {
3136-
var properties = getPropertiesOfType(type);
3137-
if (properties.length) {
3138-
var widenedTypes: Type[] = [];
3139-
var propTypeWasWidened: boolean = false;
3140-
forEach(properties, p => {
3141-
var propType = getTypeOfSymbol(p);
3142-
var widenedType = getWidenedType(propType);
3143-
if (propType !== widenedType) {
3144-
propTypeWasWidened = true;
3145-
3146-
if (program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
3147-
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
3148-
}
3149-
}
3150-
widenedTypes.push(widenedType);
3151-
});
3152-
if (propTypeWasWidened) {
3153-
var members: SymbolTable = {};
3154-
var index = 0;
3155-
forEach(properties, p => {
3156-
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
3157-
symbol.declarations = p.declarations;
3158-
symbol.parent = p.parent;
3159-
symbol.type = widenedTypes[index++];
3160-
symbol.target = p;
3161-
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
3162-
members[symbol.name] = symbol;
3163-
});
3164-
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
3165-
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
3166-
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
3167-
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
3168-
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
3169-
}
3170-
}
3171-
return type;
3172-
}
3173-
31743135
function isArrayType(type: Type): boolean {
31753136
return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
31763137
}
@@ -3183,17 +3144,8 @@ module ts {
31833144
return type;
31843145
}
31853146

3186-
function getWidenedTypeOfArrayLiteral(type: Type): Type {
3187-
var elementType = (<TypeReference>type).typeArguments[0];
3188-
var widenedType = getWidenedType(elementType);
3189-
3190-
type = elementType !== widenedType ? createArrayType(widenedType) : type;
3191-
3192-
return type;
3193-
}
3194-
31953147
/* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
3196-
function getWidenedType(type: Type): Type {
3148+
function getWidenedType(type: Type, supressNoImplicitAnyErrors?: boolean): Type {
31973149
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
31983150
return anyType;
31993151
}
@@ -3204,6 +3156,54 @@ module ts {
32043156
return getWidenedTypeOfArrayLiteral(type);
32053157
}
32063158
return type;
3159+
3160+
function getWidenedTypeOfObjectLiteral(type: Type): Type {
3161+
var properties = getPropertiesOfType(type);
3162+
if (properties.length) {
3163+
var widenedTypes: Type[] = [];
3164+
var propTypeWasWidened: boolean = false;
3165+
forEach(properties, p => {
3166+
var propType = getTypeOfSymbol(p);
3167+
var widenedType = getWidenedType(propType);
3168+
if (propType !== widenedType) {
3169+
propTypeWasWidened = true;
3170+
3171+
if (!supressNoImplicitAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
3172+
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
3173+
}
3174+
}
3175+
widenedTypes.push(widenedType);
3176+
});
3177+
if (propTypeWasWidened) {
3178+
var members: SymbolTable = {};
3179+
var index = 0;
3180+
forEach(properties, p => {
3181+
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
3182+
symbol.declarations = p.declarations;
3183+
symbol.parent = p.parent;
3184+
symbol.type = widenedTypes[index++];
3185+
symbol.target = p;
3186+
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
3187+
members[symbol.name] = symbol;
3188+
});
3189+
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
3190+
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
3191+
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
3192+
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
3193+
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
3194+
}
3195+
}
3196+
return type;
3197+
}
3198+
3199+
function getWidenedTypeOfArrayLiteral(type: Type): Type {
3200+
var elementType = (<TypeReference>type).typeArguments[0];
3201+
var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors);
3202+
3203+
type = elementType !== widenedType ? createArrayType(widenedType) : type;
3204+
3205+
return type;
3206+
}
32073207
}
32083208

32093209
function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
@@ -4329,7 +4329,7 @@ module ts {
43294329
var exprType = checkExpression(node.operand);
43304330
var targetType = getTypeFromTypeNode(node.type);
43314331
if (fullTypeCheck && targetType !== unknownType) {
4332-
var widenedType = getWidenedType(exprType);
4332+
var widenedType = getWidenedType(exprType, /*supressNoImplicitAnyErrors*/ true);
43334333
if (!(isTypeAssignableTo(targetType, widenedType))) {
43344334
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
43354335
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
==== tests/cases/compiler/noImplicitAnyInCastExpression.ts (1 errors) ====
2+
3+
// verify no noImplictAny errors reported with cast expression
4+
5+
interface IFoo {
6+
a: number;
7+
b: string;
8+
}
9+
10+
// Expr type not assignable to target type
11+
(<IFoo>{ a: null });
12+
13+
// Expr type assignable to target type
14+
(<IFoo>{ a: 2, b: undefined });
15+
16+
// Neither types is assignable to each other
17+
(<IFoo>{ c: null });
18+
~~~~~~~~~~~~~~~~~
19+
!!! Neither type '{ c: null; }' nor type 'IFoo' is assignable to the other:
20+
!!! Property 'a' is missing in type '{ c: null; }'.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [noImplicitAnyInCastExpression.ts]
2+
3+
// verify no noImplictAny errors reported with cast expression
4+
5+
interface IFoo {
6+
a: number;
7+
b: string;
8+
}
9+
10+
// Expr type not assignable to target type
11+
(<IFoo>{ a: null });
12+
13+
// Expr type assignable to target type
14+
(<IFoo>{ a: 2, b: undefined });
15+
16+
// Neither types is assignable to each other
17+
(<IFoo>{ c: null });
18+
19+
//// [noImplicitAnyInCastExpression.js]
20+
// verify no noImplictAny errors reported with cast expression
21+
// Expr type not assignable to target type
22+
{ a: null };
23+
// Expr type assignable to target type
24+
{ a: 2, b: undefined };
25+
// Neither types is assignable to each other
26+
{ c: null };
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@noImplicitAny: true
2+
3+
// verify no noImplictAny errors reported with cast expression
4+
5+
interface IFoo {
6+
a: number;
7+
b: string;
8+
}
9+
10+
// Expr type not assignable to target type
11+
(<IFoo>{ a: null });
12+
13+
// Expr type assignable to target type
14+
(<IFoo>{ a: 2, b: undefined });
15+
16+
// Neither types is assignable to each other
17+
(<IFoo>{ c: null });

0 commit comments

Comments
 (0)