From 5422e56d4805af8518480cce7fc6c5714258f6c7 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 4 Sep 2014 14:23:57 -0700 Subject: [PATCH 1/4] Do not show noImplictAny errors when widening for a cast expression --- src/compiler/checker.ts | 22 +++++++------- .../noImplicitAnyInCastExpression.js | 20 +++++++++++++ .../noImplicitAnyInCastExpression.types | 30 +++++++++++++++++++ .../compiler/noImplicitAnyInCastExpression.ts | 12 ++++++++ 4 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/noImplicitAnyInCastExpression.js create mode 100644 tests/baselines/reference/noImplicitAnyInCastExpression.types create mode 100644 tests/cases/compiler/noImplicitAnyInCastExpression.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6ca1e1e81a5..a55dbb6e345 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3132,7 +3132,7 @@ module ts { return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false; } - function getWidenedTypeOfObjectLiteral(type: Type): Type { + function getWidenedTypeOfObjectLiteral(type: Type, supressNoImplictAnyErrors?: boolean): Type { var properties = getPropertiesOfType(type); if (properties.length) { var widenedTypes: Type[] = []; @@ -3143,7 +3143,7 @@ module ts { if (propType !== widenedType) { propTypeWasWidened = true; - if (program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { + if (!supressNoImplictAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType)); } } @@ -3183,9 +3183,9 @@ module ts { return type; } - function getWidenedTypeOfArrayLiteral(type: Type): Type { + function getWidenedTypeOfArrayLiteral(type: Type, supressNoImplictAnyErrors?: boolean): Type { var elementType = (type).typeArguments[0]; - var widenedType = getWidenedType(elementType); + var widenedType = getWidenedType(elementType, supressNoImplictAnyErrors); type = elementType !== widenedType ? createArrayType(widenedType) : type; @@ -3193,15 +3193,15 @@ module ts { } /* 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, supressNoImplictAnyErrors?: boolean): Type { if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) { return anyType; } if (isTypeOfObjectLiteral(type)) { - return getWidenedTypeOfObjectLiteral(type); + return getWidenedTypeOfObjectLiteral(type, supressNoImplictAnyErrors); } if (isArrayType(type)) { - return getWidenedTypeOfArrayLiteral(type); + return getWidenedTypeOfArrayLiteral(type, supressNoImplictAnyErrors); } return type; } @@ -4329,9 +4329,11 @@ module ts { var exprType = checkExpression(node.operand); var targetType = getTypeFromTypeNode(node.type); if (fullTypeCheck && targetType !== unknownType) { - var widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(exprType, targetType) || isTypeAssignableTo(targetType, widenedType))) { - checkTypeAssignableTo(targetType, widenedType, 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); + if (!isTypeAssignableTo(exprType, targetType)) { + var widenedType = getWidenedType(exprType, /*supressNoImplictAnyErrors*/ true); + if (!isTypeAssignableTo(targetType, widenedType)) { + checkTypeAssignableTo(targetType, widenedType, 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); + } } } return targetType; diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.js b/tests/baselines/reference/noImplicitAnyInCastExpression.js new file mode 100644 index 00000000000..eef614450b4 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.js @@ -0,0 +1,20 @@ +//// [noImplicitAnyInCastExpression.ts] +interface IBar { + b: number; +} +interface IFoo { + p: IBar[]; +} + +function foo(a: any) { } + +foo( { + p: null, +}); + +//// [noImplicitAnyInCastExpression.js] +function foo(a) { +} +foo({ + p: null +}); diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.types b/tests/baselines/reference/noImplicitAnyInCastExpression.types new file mode 100644 index 00000000000..cdc0a550081 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.types @@ -0,0 +1,30 @@ +=== tests/cases/compiler/noImplicitAnyInCastExpression.ts === +interface IBar { +>IBar : IBar + + b: number; +>b : number +} +interface IFoo { +>IFoo : IFoo + + p: IBar[]; +>p : IBar[] +>IBar : IBar +} + +function foo(a: any) { } +>foo : (a: any) => void +>a : any + +foo( { +>foo( { p: null,}) : void +>foo : (a: any) => void +> { p: null,} : IFoo +>IFoo : IFoo +>{ p: null,} : { p: null; } + + p: null, +>p : any + +}); diff --git a/tests/cases/compiler/noImplicitAnyInCastExpression.ts b/tests/cases/compiler/noImplicitAnyInCastExpression.ts new file mode 100644 index 00000000000..9838e5e9432 --- /dev/null +++ b/tests/cases/compiler/noImplicitAnyInCastExpression.ts @@ -0,0 +1,12 @@ +interface IBar { + b: number; +} +interface IFoo { + p: IBar[]; +} + +function foo(a: any) { } + +foo( { + p: null, +}); \ No newline at end of file From 3b6afb84994d7408a28caba58fc046b29a0a6753 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 5 Sep 2014 16:41:37 -0700 Subject: [PATCH 2/4] respond to code review remarks --- src/compiler/checker.ts | 19 +++++------ .../baselines/reference/arrayCast.errors.txt | 3 +- .../reference/contextualTyping39.errors.txt | 3 +- .../reference/contextualTyping41.errors.txt | 3 +- tests/baselines/reference/fuzzy.errors.txt | 5 ++- .../genericTypeAssertions2.errors.txt | 3 +- .../genericTypeAssertions4.errors.txt | 6 ++-- .../genericTypeAssertions5.errors.txt | 6 ++-- .../reference/intTypeCheck.errors.txt | 3 +- .../noImplicitAnyInCastExpression.errors.txt | 20 ++++++++++++ .../noImplicitAnyInCastExpression.js | 32 +++++++++++-------- .../noImplicitAnyInCastExpression.types | 30 ----------------- .../reference/typeAssertions.errors.txt | 6 ++-- .../compiler/noImplicitAnyInCastExpression.ts | 21 +++++++----- 14 files changed, 86 insertions(+), 74 deletions(-) create mode 100644 tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt delete mode 100644 tests/baselines/reference/noImplicitAnyInCastExpression.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a55dbb6e345..932c8496694 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3132,7 +3132,7 @@ module ts { return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false; } - function getWidenedTypeOfObjectLiteral(type: Type, supressNoImplictAnyErrors?: boolean): Type { + function getWidenedTypeOfObjectLiteral(type: Type, supressNoImplicitAnyErrors?: boolean): Type { var properties = getPropertiesOfType(type); if (properties.length) { var widenedTypes: Type[] = []; @@ -3143,7 +3143,7 @@ module ts { if (propType !== widenedType) { propTypeWasWidened = true; - if (!supressNoImplictAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) { + 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)); } } @@ -3183,9 +3183,9 @@ module ts { return type; } - function getWidenedTypeOfArrayLiteral(type: Type, supressNoImplictAnyErrors?: boolean): Type { + function getWidenedTypeOfArrayLiteral(type: Type, supressNoImplicitAnyErrors?: boolean): Type { var elementType = (type).typeArguments[0]; - var widenedType = getWidenedType(elementType, supressNoImplictAnyErrors); + var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors); type = elementType !== widenedType ? createArrayType(widenedType) : type; @@ -3193,15 +3193,15 @@ module ts { } /* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */ - function getWidenedType(type: Type, supressNoImplictAnyErrors?: boolean): Type { + function getWidenedType(type: Type, supressNoImplicitAnyErrors?: boolean): Type { if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) { return anyType; } if (isTypeOfObjectLiteral(type)) { - return getWidenedTypeOfObjectLiteral(type, supressNoImplictAnyErrors); + return getWidenedTypeOfObjectLiteral(type, supressNoImplicitAnyErrors); } if (isArrayType(type)) { - return getWidenedTypeOfArrayLiteral(type, supressNoImplictAnyErrors); + return getWidenedTypeOfArrayLiteral(type, supressNoImplicitAnyErrors); } return type; } @@ -4330,10 +4330,7 @@ module ts { var targetType = getTypeFromTypeNode(node.type); if (fullTypeCheck && targetType !== unknownType) { if (!isTypeAssignableTo(exprType, targetType)) { - var widenedType = getWidenedType(exprType, /*supressNoImplictAnyErrors*/ true); - if (!isTypeAssignableTo(targetType, widenedType)) { - checkTypeAssignableTo(targetType, widenedType, 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); - } + checkTypeAssignableTo(targetType, getWidenedType(exprType, /*supressNoImplicitAnyErrors*/ true), 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); } } return targetType; diff --git a/tests/baselines/reference/arrayCast.errors.txt b/tests/baselines/reference/arrayCast.errors.txt index f081e0008d9..5ca2bc4b2b2 100644 --- a/tests/baselines/reference/arrayCast.errors.txt +++ b/tests/baselines/reference/arrayCast.errors.txt @@ -4,7 +4,8 @@ <{ id: number; }[]>[{ foo: "s" }]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! Neither type '{ id: number; }[]' nor type '{ foo: string; }[]' is assignable to the other: -!!! Type '{ id: number; }' is not assignable to type '{ foo: string; }'. +!!! Type '{ id: number; }' is not assignable to type '{ foo: string; }': +!!! Property 'foo' is missing in type '{ id: number; }'. // Should succeed, as the {} element causes the type of the array to be {}[] <{ id: number; }[]>[{ foo: "s" }, {}]; \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping39.errors.txt b/tests/baselines/reference/contextualTyping39.errors.txt index c0907b8fe7b..85ecf5e35b0 100644 --- a/tests/baselines/reference/contextualTyping39.errors.txt +++ b/tests/baselines/reference/contextualTyping39.errors.txt @@ -1,4 +1,5 @@ ==== tests/cases/compiler/contextualTyping39.ts (1 errors) ==== var foo = <{ (): number; }> function() { return "err"; }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! Neither type '() => number' nor type '() => string' is assignable to the other. \ No newline at end of file +!!! Neither type '() => number' nor type '() => string' is assignable to the other: +!!! Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping41.errors.txt b/tests/baselines/reference/contextualTyping41.errors.txt index d74e45f8a08..7f760b09b80 100644 --- a/tests/baselines/reference/contextualTyping41.errors.txt +++ b/tests/baselines/reference/contextualTyping41.errors.txt @@ -1,4 +1,5 @@ ==== tests/cases/compiler/contextualTyping41.ts (1 errors) ==== var foo = <{():number; (i:number):number; }> (function(){return "err";}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! Neither type '{ (): number; (i: number): number; }' nor type '() => string' is assignable to the other. \ No newline at end of file +!!! Neither type '{ (): number; (i: number): number; }' nor type '() => string' is assignable to the other: +!!! Type 'number' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/fuzzy.errors.txt b/tests/baselines/reference/fuzzy.errors.txt index dfe667b5be9..12060d90c98 100644 --- a/tests/baselines/reference/fuzzy.errors.txt +++ b/tests/baselines/reference/fuzzy.errors.txt @@ -32,7 +32,10 @@ worksToo():R { return ({ oneI: this }); ~~~~~~~~~~~~~~~~~~~ -!!! Neither type 'R' nor type '{ oneI: C; }' is assignable to the other. +!!! Neither type 'R' nor type '{ oneI: C; }' is assignable to the other: +!!! Types of property 'oneI' are incompatible: +!!! Type 'I' is not assignable to type 'C': +!!! Property 'x' is missing in type 'I'. } } } diff --git a/tests/baselines/reference/genericTypeAssertions2.errors.txt b/tests/baselines/reference/genericTypeAssertions2.errors.txt index e2f874b5983..cc49ef77810 100644 --- a/tests/baselines/reference/genericTypeAssertions2.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions2.errors.txt @@ -22,4 +22,5 @@ var r4: A = >new A(); var r5: A = >[]; // error ~~~~~~~~~~~~~ -!!! Neither type 'A' nor type 'any[]' is assignable to the other. \ No newline at end of file +!!! Neither type 'A' nor type 'any[]' is assignable to the other: +!!! Property 'length' is missing in type 'A'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions4.errors.txt b/tests/baselines/reference/genericTypeAssertions4.errors.txt index 13a4e2929b3..222b14c0850 100644 --- a/tests/baselines/reference/genericTypeAssertions4.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions4.errors.txt @@ -29,8 +29,10 @@ y = a; y = b; // error: cannot convert B to T ~~~~ -!!! Neither type 'T' nor type 'B' is assignable to the other. +!!! Neither type 'T' nor type 'B' is assignable to the other: +!!! Property 'bar' is missing in type 'A'. y = c; // error: cannot convert C to T ~~~~ -!!! Neither type 'T' nor type 'C' is assignable to the other. +!!! Neither type 'T' nor type 'C' is assignable to the other: +!!! Property 'baz' is missing in type 'A'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions5.errors.txt b/tests/baselines/reference/genericTypeAssertions5.errors.txt index 7b25b898213..97b4b7555c7 100644 --- a/tests/baselines/reference/genericTypeAssertions5.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions5.errors.txt @@ -29,8 +29,10 @@ y = a; y = b; // error: cannot convert B to T ~~~~ -!!! Neither type 'T' nor type 'B' is assignable to the other. +!!! Neither type 'T' nor type 'B' is assignable to the other: +!!! Property 'bar' is missing in type 'A'. y = c; // error: cannot convert C to T ~~~~ -!!! Neither type 'T' nor type 'C' is assignable to the other. +!!! Neither type 'T' nor type 'C' is assignable to the other: +!!! Property 'baz' is missing in type 'A'. } \ No newline at end of file diff --git a/tests/baselines/reference/intTypeCheck.errors.txt b/tests/baselines/reference/intTypeCheck.errors.txt index cb2075efbdc..60c834dd0ea 100644 --- a/tests/baselines/reference/intTypeCheck.errors.txt +++ b/tests/baselines/reference/intTypeCheck.errors.txt @@ -315,7 +315,8 @@ var obj69: i7 = new obj66; var obj70: i7 = new Base; ~~~~~~~~~~~~ -!!! Neither type 'i7' nor type 'Base' is assignable to the other. +!!! Neither type 'i7' nor type 'Base' is assignable to the other: +!!! Property 'foo' is missing in type 'i7'. var obj71: i7 = null; var obj72: i7 = function () { }; ~~~~~ diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt new file mode 100644 index 00000000000..2784467da94 --- /dev/null +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt @@ -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 + ({ a: null }); + + // Expr type assignanle to target type + ({ a: 2, b: undefined }); + + // Niether types is assignable to each other + ({ c: null }); + ~~~~~~~~~~~~~~~~~ +!!! Neither type 'IFoo' nor type '{ c: any; }' is assignable to the other: +!!! Property 'c' is missing in type 'IFoo'. \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.js b/tests/baselines/reference/noImplicitAnyInCastExpression.js index eef614450b4..6501d17a5fe 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.js +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.js @@ -1,20 +1,26 @@ //// [noImplicitAnyInCastExpression.ts] -interface IBar { - b: number; -} + +// verify no noImplictAny errors reported with cast expression + interface IFoo { - p: IBar[]; + a: number; + b: string; } -function foo(a: any) { } +// Expr type not assignable to target type +({ a: null }); -foo( { - p: null, -}); +// Expr type assignanle to target type +({ a: 2, b: undefined }); + +// Niether types is assignable to each other +({ c: null }); //// [noImplicitAnyInCastExpression.js] -function foo(a) { -} -foo({ - p: null -}); +// verify no noImplictAny errors reported with cast expression +// Expr type not assignable to target type +{ a: null }; +// Expr type assignanle to target type +{ a: 2, b: undefined }; +// Niether types is assignable to each other +{ c: null }; diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.types b/tests/baselines/reference/noImplicitAnyInCastExpression.types deleted file mode 100644 index cdc0a550081..00000000000 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.types +++ /dev/null @@ -1,30 +0,0 @@ -=== tests/cases/compiler/noImplicitAnyInCastExpression.ts === -interface IBar { ->IBar : IBar - - b: number; ->b : number -} -interface IFoo { ->IFoo : IFoo - - p: IBar[]; ->p : IBar[] ->IBar : IBar -} - -function foo(a: any) { } ->foo : (a: any) => void ->a : any - -foo( { ->foo( { p: null,}) : void ->foo : (a: any) => void -> { p: null,} : IFoo ->IFoo : IFoo ->{ p: null,} : { p: null; } - - p: null, ->p : any - -}); diff --git a/tests/baselines/reference/typeAssertions.errors.txt b/tests/baselines/reference/typeAssertions.errors.txt index 47f3a3c930c..6a82f17a0db 100644 --- a/tests/baselines/reference/typeAssertions.errors.txt +++ b/tests/baselines/reference/typeAssertions.errors.txt @@ -33,13 +33,15 @@ someBase = someBase; someBase = someOther; // Error ~~~~~~~~~~~~~~~~~~~ -!!! Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other. +!!! Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other: +!!! Property 'q' is missing in type 'SomeBase'. someDerived = someDerived; someDerived = someBase; someDerived = someOther; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! Neither type 'SomeDerived' nor type 'SomeOther' is assignable to the other. +!!! Neither type 'SomeDerived' nor type 'SomeOther' is assignable to the other: +!!! Property 'q' is missing in type 'SomeDerived'. someOther = someDerived; // Error ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/cases/compiler/noImplicitAnyInCastExpression.ts b/tests/cases/compiler/noImplicitAnyInCastExpression.ts index 9838e5e9432..afbdfa1ec1e 100644 --- a/tests/cases/compiler/noImplicitAnyInCastExpression.ts +++ b/tests/cases/compiler/noImplicitAnyInCastExpression.ts @@ -1,12 +1,17 @@ -interface IBar { - b: number; -} +//@noImplicitAny: true + +// verify no noImplictAny errors reported with cast expression + interface IFoo { - p: IBar[]; + a: number; + b: string; } -function foo(a: any) { } +// Expr type not assignable to target type +({ a: null }); -foo( { - p: null, -}); \ No newline at end of file +// Expr type assignanle to target type +({ a: 2, b: undefined }); + +// Niether types is assignable to each other +({ c: null }); \ No newline at end of file From b3260653cefa140c3482b6c6464369d4b838b468 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Fri, 5 Sep 2014 16:45:30 -0700 Subject: [PATCH 3/4] move getWidenedType* functions inside the getWidenedType function scope --- src/compiler/checker.ts | 100 ++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 932c8496694..289ff68bc40 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3132,45 +3132,6 @@ module ts { return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false; } - function getWidenedTypeOfObjectLiteral(type: Type, supressNoImplicitAnyErrors?: boolean): 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 = 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 && (type).target === globalArrayType; } @@ -3183,27 +3144,66 @@ module ts { return type; } - function getWidenedTypeOfArrayLiteral(type: Type, supressNoImplicitAnyErrors?: boolean): Type { - var elementType = (type).typeArguments[0]; - var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors); - - 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, supressNoImplicitAnyErrors?: boolean): Type { if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) { return anyType; } if (isTypeOfObjectLiteral(type)) { - return getWidenedTypeOfObjectLiteral(type, supressNoImplicitAnyErrors); + return getWidenedTypeOfObjectLiteral(type); } if (isArrayType(type)) { - return getWidenedTypeOfArrayLiteral(type, supressNoImplicitAnyErrors); + 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 = 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 = (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) { From 4f21fb59a2f45a392ef879f33afed21f27b68c89 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 8 Sep 2014 12:08:15 -0700 Subject: [PATCH 4/4] fix typo --- .../reference/noImplicitAnyInCastExpression.errors.txt | 4 ++-- .../baselines/reference/noImplicitAnyInCastExpression.js | 8 ++++---- tests/cases/compiler/noImplicitAnyInCastExpression.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt index 271f869360f..bc7542df511 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt @@ -10,10 +10,10 @@ // Expr type not assignable to target type ({ a: null }); - // Expr type assignanle to target type + // Expr type assignable to target type ({ a: 2, b: undefined }); - // Niether types is assignable to each other + // Neither types is assignable to each other ({ c: null }); ~~~~~~~~~~~~~~~~~ !!! Neither type '{ c: null; }' nor type 'IFoo' is assignable to the other: diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.js b/tests/baselines/reference/noImplicitAnyInCastExpression.js index 6501d17a5fe..1b7cc59c7c0 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.js +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.js @@ -10,17 +10,17 @@ interface IFoo { // Expr type not assignable to target type ({ a: null }); -// Expr type assignanle to target type +// Expr type assignable to target type ({ a: 2, b: undefined }); -// Niether types is assignable to each other +// Neither types is assignable to each other ({ c: null }); //// [noImplicitAnyInCastExpression.js] // verify no noImplictAny errors reported with cast expression // Expr type not assignable to target type { a: null }; -// Expr type assignanle to target type +// Expr type assignable to target type { a: 2, b: undefined }; -// Niether types is assignable to each other +// Neither types is assignable to each other { c: null }; diff --git a/tests/cases/compiler/noImplicitAnyInCastExpression.ts b/tests/cases/compiler/noImplicitAnyInCastExpression.ts index afbdfa1ec1e..5566b898a07 100644 --- a/tests/cases/compiler/noImplicitAnyInCastExpression.ts +++ b/tests/cases/compiler/noImplicitAnyInCastExpression.ts @@ -10,8 +10,8 @@ interface IFoo { // Expr type not assignable to target type ({ a: null }); -// Expr type assignanle to target type +// Expr type assignable to target type ({ a: 2, b: undefined }); -// Niether types is assignable to each other +// Neither types is assignable to each other ({ c: null }); \ No newline at end of file