@@ -3720,6 +3720,7 @@ module ts {
37203720 for ( var i = 0 ; i < typeParameters . length ; i ++ ) inferences . push ( [ ] ) ;
37213721 return {
37223722 typeParameters : typeParameters ,
3723+ inferenceCount : 0 ,
37233724 inferences : inferences ,
37243725 inferredTypes : new Array ( typeParameters . length ) ,
37253726 } ;
@@ -3757,6 +3758,7 @@ module ts {
37573758 var typeParameters = context . typeParameters ;
37583759 for ( var i = 0 ; i < typeParameters . length ; i ++ ) {
37593760 if ( target === typeParameters [ i ] ) {
3761+ context . inferenceCount ++ ;
37603762 var inferences = context . inferences [ i ] ;
37613763 if ( ! contains ( inferences , source ) ) inferences . push ( source ) ;
37623764 break ;
@@ -3771,6 +3773,35 @@ module ts {
37713773 inferFromTypes ( sourceTypes [ i ] , targetTypes [ i ] ) ;
37723774 }
37733775 }
3776+ else if ( target . flags & TypeFlags . Union ) {
3777+ // Target is a union type
3778+ var targetTypes = ( < UnionType > target ) . types ;
3779+ var startCount = context . inferenceCount ;
3780+ var typeParameterCount = 0 ;
3781+ var typeParameter : TypeParameter ;
3782+ // First infer to each type in union that isn't a type parameter
3783+ for ( var i = 0 ; i < targetTypes . length ; i ++ ) {
3784+ var t = targetTypes [ i ] ;
3785+ if ( t . flags & TypeFlags . TypeParameter && contains ( context . typeParameters , t ) ) {
3786+ typeParameter = < TypeParameter > t ;
3787+ typeParameterCount ++ ;
3788+ }
3789+ else {
3790+ inferFromTypes ( source , t ) ;
3791+ }
3792+ }
3793+ // If no inferences were produced above and union contains a single naked type parameter, infer to that type parameter
3794+ if ( context . inferenceCount === startCount && typeParameterCount === 1 ) {
3795+ inferFromTypes ( source , typeParameter ) ;
3796+ }
3797+ }
3798+ else if ( source . flags & TypeFlags . Union ) {
3799+ // Source is a union type, infer from each consituent type
3800+ var sourceTypes = ( < UnionType > source ) . types ;
3801+ for ( var i = 0 ; i < sourceTypes . length ; i ++ ) {
3802+ inferFromTypes ( sourceTypes [ i ] , target ) ;
3803+ }
3804+ }
37743805 else if ( source . flags & TypeFlags . ObjectType && ( target . flags & ( TypeFlags . Reference | TypeFlags . Tuple ) ||
37753806 ( target . flags & TypeFlags . Anonymous ) && target . symbol && target . symbol . flags & ( SymbolFlags . Method | SymbolFlags . TypeLiteral ) ) ) {
37763807 // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
@@ -5169,7 +5200,9 @@ module ts {
51695200
51705201 // Try to return the best common type if we have any return expressions.
51715202 if ( types . length > 0 ) {
5172- var commonType = getCommonSupertype ( types ) ;
5203+ // When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
5204+ // return expressions to have a best common supertype.
5205+ var commonType = getContextualSignature ( func ) ? getUnionType ( types ) : getCommonSupertype ( types ) ;
51735206 if ( ! commonType ) {
51745207 error ( func , Diagnostics . No_best_common_type_exists_among_return_expressions ) ;
51755208
0 commit comments