mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-12 03:20:56 -06:00
Merge pull request #602 from Microsoft/noImplicitAnyOnCast
Do not show noImplictAny errors when widening for a cast expression
This commit is contained in:
commit
6fee404152
@ -3132,45 +3132,6 @@ module ts {
|
||||
return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
|
||||
}
|
||||
|
||||
function getWidenedTypeOfObjectLiteral(type: Type): Type {
|
||||
var properties = getPropertiesOfType(type);
|
||||
if (properties.length) {
|
||||
var widenedTypes: Type[] = [];
|
||||
var propTypeWasWidened: boolean = false;
|
||||
forEach(properties, p => {
|
||||
var propType = getTypeOfSymbol(p);
|
||||
var widenedType = getWidenedType(propType);
|
||||
if (propType !== widenedType) {
|
||||
propTypeWasWidened = true;
|
||||
|
||||
if (program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
|
||||
}
|
||||
}
|
||||
widenedTypes.push(widenedType);
|
||||
});
|
||||
if (propTypeWasWidened) {
|
||||
var members: SymbolTable = {};
|
||||
var index = 0;
|
||||
forEach(properties, p => {
|
||||
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
|
||||
symbol.declarations = p.declarations;
|
||||
symbol.parent = p.parent;
|
||||
symbol.type = widenedTypes[index++];
|
||||
symbol.target = p;
|
||||
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
|
||||
members[symbol.name] = symbol;
|
||||
});
|
||||
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
|
||||
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
|
||||
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
|
||||
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
|
||||
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function isArrayType(type: Type): boolean {
|
||||
return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
|
||||
}
|
||||
@ -3183,17 +3144,8 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getWidenedTypeOfArrayLiteral(type: Type): Type {
|
||||
var elementType = (<TypeReference>type).typeArguments[0];
|
||||
var widenedType = getWidenedType(elementType);
|
||||
|
||||
type = elementType !== widenedType ? createArrayType(widenedType) : type;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
|
||||
function getWidenedType(type: Type): Type {
|
||||
function getWidenedType(type: Type, supressNoImplicitAnyErrors?: boolean): Type {
|
||||
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
|
||||
return anyType;
|
||||
}
|
||||
@ -3204,6 +3156,54 @@ module ts {
|
||||
return getWidenedTypeOfArrayLiteral(type);
|
||||
}
|
||||
return type;
|
||||
|
||||
function getWidenedTypeOfObjectLiteral(type: Type): Type {
|
||||
var properties = getPropertiesOfType(type);
|
||||
if (properties.length) {
|
||||
var widenedTypes: Type[] = [];
|
||||
var propTypeWasWidened: boolean = false;
|
||||
forEach(properties, p => {
|
||||
var propType = getTypeOfSymbol(p);
|
||||
var widenedType = getWidenedType(propType);
|
||||
if (propType !== widenedType) {
|
||||
propTypeWasWidened = true;
|
||||
|
||||
if (!supressNoImplicitAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
|
||||
}
|
||||
}
|
||||
widenedTypes.push(widenedType);
|
||||
});
|
||||
if (propTypeWasWidened) {
|
||||
var members: SymbolTable = {};
|
||||
var index = 0;
|
||||
forEach(properties, p => {
|
||||
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
|
||||
symbol.declarations = p.declarations;
|
||||
symbol.parent = p.parent;
|
||||
symbol.type = widenedTypes[index++];
|
||||
symbol.target = p;
|
||||
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
|
||||
members[symbol.name] = symbol;
|
||||
});
|
||||
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
|
||||
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
|
||||
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
|
||||
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
|
||||
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getWidenedTypeOfArrayLiteral(type: Type): Type {
|
||||
var elementType = (<TypeReference>type).typeArguments[0];
|
||||
var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors);
|
||||
|
||||
type = elementType !== widenedType ? createArrayType(widenedType) : type;
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
|
||||
@ -4329,7 +4329,7 @@ module ts {
|
||||
var exprType = checkExpression(node.operand);
|
||||
var targetType = getTypeFromTypeNode(node.type);
|
||||
if (fullTypeCheck && targetType !== unknownType) {
|
||||
var widenedType = getWidenedType(exprType);
|
||||
var widenedType = getWidenedType(exprType, /*supressNoImplicitAnyErrors*/ true);
|
||||
if (!(isTypeAssignableTo(targetType, widenedType))) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
==== tests/cases/compiler/noImplicitAnyInCastExpression.ts (1 errors) ====
|
||||
|
||||
// verify no noImplictAny errors reported with cast expression
|
||||
|
||||
interface IFoo {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
|
||||
// Expr type not assignable to target type
|
||||
(<IFoo>{ a: null });
|
||||
|
||||
// Expr type assignable to target type
|
||||
(<IFoo>{ a: 2, b: undefined });
|
||||
|
||||
// Neither types is assignable to each other
|
||||
(<IFoo>{ c: null });
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! Neither type '{ c: null; }' nor type 'IFoo' is assignable to the other:
|
||||
!!! Property 'a' is missing in type '{ c: null; }'.
|
||||
26
tests/baselines/reference/noImplicitAnyInCastExpression.js
Normal file
26
tests/baselines/reference/noImplicitAnyInCastExpression.js
Normal file
@ -0,0 +1,26 @@
|
||||
//// [noImplicitAnyInCastExpression.ts]
|
||||
|
||||
// verify no noImplictAny errors reported with cast expression
|
||||
|
||||
interface IFoo {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
|
||||
// Expr type not assignable to target type
|
||||
(<IFoo>{ a: null });
|
||||
|
||||
// Expr type assignable to target type
|
||||
(<IFoo>{ a: 2, b: undefined });
|
||||
|
||||
// Neither types is assignable to each other
|
||||
(<IFoo>{ c: null });
|
||||
|
||||
//// [noImplicitAnyInCastExpression.js]
|
||||
// verify no noImplictAny errors reported with cast expression
|
||||
// Expr type not assignable to target type
|
||||
{ a: null };
|
||||
// Expr type assignable to target type
|
||||
{ a: 2, b: undefined };
|
||||
// Neither types is assignable to each other
|
||||
{ c: null };
|
||||
17
tests/cases/compiler/noImplicitAnyInCastExpression.ts
Normal file
17
tests/cases/compiler/noImplicitAnyInCastExpression.ts
Normal file
@ -0,0 +1,17 @@
|
||||
//@noImplicitAny: true
|
||||
|
||||
// verify no noImplictAny errors reported with cast expression
|
||||
|
||||
interface IFoo {
|
||||
a: number;
|
||||
b: string;
|
||||
}
|
||||
|
||||
// Expr type not assignable to target type
|
||||
(<IFoo>{ a: null });
|
||||
|
||||
// Expr type assignable to target type
|
||||
(<IFoo>{ a: 2, b: undefined });
|
||||
|
||||
// Neither types is assignable to each other
|
||||
(<IFoo>{ c: null });
|
||||
Loading…
x
Reference in New Issue
Block a user