From a01df0f20beef355f0902eb54019e7018fde5576 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Oct 2017 12:36:25 -0700 Subject: [PATCH 1/8] Use nominal check in isTypeInstanceOf --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 72438fa27af87..864e78aa0e99e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8556,11 +8556,14 @@ namespace ts { return isTypeRelatedTo(source, target, assignableRelation); } - // A type S is considered to be an instance of a type T if S and T are the same type or if S is a - // subtype of T but not structurally identical to T. This specifically means that two distinct but - // structurally identical types (such as two classes) are not considered instances of each other. + // An object type S is considered to be an instance of an object type T if + // S is a union type and every constituent of S is an instance of T, + // T is a union type and S is an instance of at least one constituent of T, or + // T occurs directly or indirectly in an 'extends' clause of S. function isTypeInstanceOf(source: Type, target: Type): boolean { - return getTargetType(source) === getTargetType(target) || isTypeSubtypeOf(source, target) && !isTypeIdenticalTo(source, target); + return source.flags & TypeFlags.Union ? every((source).types, t => isTypeInstanceOf(t, target)) : + target.flags & TypeFlags.Union ? some((target).types, t => isTypeInstanceOf(source, t)) : + hasBaseType(source, getTargetType(target)); } /** From d6697714629b3c204fdbadca1452480b436bd09c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Oct 2017 12:36:34 -0700 Subject: [PATCH 2/8] Accept new baselines --- .../narrowingGenericTypeFromInstanceof01.errors.txt | 10 ++++------ .../narrowingGenericTypeFromInstanceof01.types | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.errors.txt b/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.errors.txt index c686cd7a7cffc..bb35b351c1b44 100644 --- a/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.errors.txt +++ b/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.errors.txt @@ -1,6 +1,5 @@ -tests/cases/conformance/types/typeRelationships/instanceOf/narrowingGenericTypeFromInstanceof01.ts(13,17): error TS2345: Argument of type 'A | B' is not assignable to parameter of type 'A'. - Type 'B' is not assignable to type 'A'. - Property 'a' is missing in type 'B'. +tests/cases/conformance/types/typeRelationships/instanceOf/narrowingGenericTypeFromInstanceof01.ts(13,17): error TS2345: Argument of type 'B' is not assignable to parameter of type 'A<{}>'. + Property 'a' is missing in type 'B'. ==== tests/cases/conformance/types/typeRelationships/instanceOf/narrowingGenericTypeFromInstanceof01.ts (1 errors) ==== @@ -18,9 +17,8 @@ tests/cases/conformance/types/typeRelationships/instanceOf/narrowingGenericTypeF if (x instanceof B) { acceptA(x); ~ -!!! error TS2345: Argument of type 'A | B' is not assignable to parameter of type 'A'. -!!! error TS2345: Type 'B' is not assignable to type 'A'. -!!! error TS2345: Property 'a' is missing in type 'B'. +!!! error TS2345: Argument of type 'B' is not assignable to parameter of type 'A<{}>'. +!!! error TS2345: Property 'a' is missing in type 'B'. } if (x instanceof A) { diff --git a/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.types b/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.types index 22d02d17ce12e..964c7920a3432 100644 --- a/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.types +++ b/tests/baselines/reference/narrowingGenericTypeFromInstanceof01.types @@ -43,7 +43,7 @@ function test(x: A | B) { acceptA(x); >acceptA(x) : any >acceptA : (a: A) => void ->x : A | B +>x : B } if (x instanceof A) { @@ -65,7 +65,7 @@ function test(x: A | B) { acceptB(x); >acceptB(x) : void >acceptB : (b: B) => void ->x : A | B +>x : B } if (x instanceof B) { @@ -76,6 +76,6 @@ function test(x: A | B) { acceptB(x); >acceptB(x) : void >acceptB : (b: B) => void ->x : A | B +>x : B } } From 3d89837cfa01a25bcf432f1d7f0077932bb9ec11 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Oct 2017 15:35:51 -0700 Subject: [PATCH 3/8] Use nominal checks in union type subtype reduction --- src/compiler/checker.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 864e78aa0e99e..058cff4d8b664 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7431,9 +7431,12 @@ namespace ts { return false; } - function isSubtypeOfAny(candidate: Type, types: Type[]): boolean { - for (const type of types) { - if (candidate !== type && isTypeSubtypeOf(candidate, type)) { + function isSubtypeOfAny(source: Type, targets: Type[]): boolean { + for (const target of targets) { + if (source !== target && isTypeSubtypeOf(source, target) && ( + !(getObjectFlags(source) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) || + !(getObjectFlags(target) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) || + isTypeDerivedFrom(source, target))) { return true; } } @@ -8556,13 +8559,15 @@ namespace ts { return isTypeRelatedTo(source, target, assignableRelation); } - // An object type S is considered to be an instance of an object type T if - // S is a union type and every constituent of S is an instance of T, - // T is a union type and S is an instance of at least one constituent of T, or + // An object type S is considered to be derived from an object type T if + // S is a union type and every constituent of S is derived from T, + // T is a union type and S is derived from at least one constituent of T, or // T occurs directly or indirectly in an 'extends' clause of S. - function isTypeInstanceOf(source: Type, target: Type): boolean { - return source.flags & TypeFlags.Union ? every((source).types, t => isTypeInstanceOf(t, target)) : - target.flags & TypeFlags.Union ? some((target).types, t => isTypeInstanceOf(source, t)) : + // Note that this check ignores type parameters and only considers the + // inheritance hierarchy. + function isTypeDerivedFrom(source: Type, target: Type): boolean { + return source.flags & TypeFlags.Union ? every((source).types, t => isTypeDerivedFrom(t, target)) : + target.flags & TypeFlags.Union ? some((target).types, t => isTypeDerivedFrom(source, t)) : hasBaseType(source, getTargetType(target)); } @@ -12411,7 +12416,7 @@ namespace ts { } if (targetType) { - return getNarrowedType(type, targetType, assumeTrue, isTypeInstanceOf); + return getNarrowedType(type, targetType, assumeTrue, isTypeDerivedFrom); } return type; From 923e7a0614dc4dae6116508e8a86c9a7df0458fb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Oct 2017 15:36:08 -0700 Subject: [PATCH 4/8] Accept new baselines --- .../reference/arrayBestCommonTypes.types | 32 +++++++++---------- .../arrayLiteralsWithRecursiveGenerics.types | 4 +-- .../controlFlowBinaryOrExpression.symbols | 4 +-- .../controlFlowBinaryOrExpression.types | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/arrayBestCommonTypes.types b/tests/baselines/reference/arrayBestCommonTypes.types index 864b1adfacba6..c146a100d1881 100644 --- a/tests/baselines/reference/arrayBestCommonTypes.types +++ b/tests/baselines/reference/arrayBestCommonTypes.types @@ -366,29 +366,29 @@ module EmptyTypes { >base2 : typeof base2 var b1 = [baseObj, base2Obj, ifaceObj]; ->b1 : iface[] ->[baseObj, base2Obj, ifaceObj] : iface[] +>b1 : (iface | base | base2)[] +>[baseObj, base2Obj, ifaceObj] : (iface | base | base2)[] >baseObj : base >base2Obj : base2 >ifaceObj : iface var b2 = [base2Obj, baseObj, ifaceObj]; ->b2 : iface[] ->[base2Obj, baseObj, ifaceObj] : iface[] +>b2 : (iface | base | base2)[] +>[base2Obj, baseObj, ifaceObj] : (iface | base | base2)[] >base2Obj : base2 >baseObj : base >ifaceObj : iface var b3 = [baseObj, ifaceObj, base2Obj]; ->b3 : iface[] ->[baseObj, ifaceObj, base2Obj] : iface[] +>b3 : (iface | base | base2)[] +>[baseObj, ifaceObj, base2Obj] : (iface | base | base2)[] >baseObj : base >ifaceObj : iface >base2Obj : base2 var b4 = [ifaceObj, baseObj, base2Obj]; ->b4 : iface[] ->[ifaceObj, baseObj, base2Obj] : iface[] +>b4 : (iface | base | base2)[] +>[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[] >ifaceObj : iface >baseObj : base >base2Obj : base2 @@ -769,29 +769,29 @@ module NonEmptyTypes { >base2 : typeof base2 var b1 = [baseObj, base2Obj, ifaceObj]; ->b1 : iface[] ->[baseObj, base2Obj, ifaceObj] : iface[] +>b1 : (iface | base | base2)[] +>[baseObj, base2Obj, ifaceObj] : (iface | base | base2)[] >baseObj : base >base2Obj : base2 >ifaceObj : iface var b2 = [base2Obj, baseObj, ifaceObj]; ->b2 : iface[] ->[base2Obj, baseObj, ifaceObj] : iface[] +>b2 : (iface | base | base2)[] +>[base2Obj, baseObj, ifaceObj] : (iface | base | base2)[] >base2Obj : base2 >baseObj : base >ifaceObj : iface var b3 = [baseObj, ifaceObj, base2Obj]; ->b3 : iface[] ->[baseObj, ifaceObj, base2Obj] : iface[] +>b3 : (iface | base | base2)[] +>[baseObj, ifaceObj, base2Obj] : (iface | base | base2)[] >baseObj : base >ifaceObj : iface >base2Obj : base2 var b4 = [ifaceObj, baseObj, base2Obj]; ->b4 : iface[] ->[ifaceObj, baseObj, base2Obj] : iface[] +>b4 : (iface | base | base2)[] +>[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[] >ifaceObj : iface >baseObj : base >base2Obj : base2 diff --git a/tests/baselines/reference/arrayLiteralsWithRecursiveGenerics.types b/tests/baselines/reference/arrayLiteralsWithRecursiveGenerics.types index 9cdbe0a0a6157..75013cdef098e 100644 --- a/tests/baselines/reference/arrayLiteralsWithRecursiveGenerics.types +++ b/tests/baselines/reference/arrayLiteralsWithRecursiveGenerics.types @@ -55,8 +55,8 @@ var myList: MyList; >MyList : MyList var xs = [list, myList]; // {}[] ->xs : List[] ->[list, myList] : List[] +>xs : (List | MyList)[] +>[list, myList] : (List | MyList)[] >list : List >myList : MyList diff --git a/tests/baselines/reference/controlFlowBinaryOrExpression.symbols b/tests/baselines/reference/controlFlowBinaryOrExpression.symbols index 5251973005fcd..e76cfbf4caba9 100644 --- a/tests/baselines/reference/controlFlowBinaryOrExpression.symbols +++ b/tests/baselines/reference/controlFlowBinaryOrExpression.symbols @@ -86,8 +86,8 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) sourceObj.length; ->sourceObj.length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27)) +>sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33)) >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) ->length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27)) +>length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33)) } diff --git a/tests/baselines/reference/controlFlowBinaryOrExpression.types b/tests/baselines/reference/controlFlowBinaryOrExpression.types index e843844ebf1e4..8a3b8a6d055bb 100644 --- a/tests/baselines/reference/controlFlowBinaryOrExpression.types +++ b/tests/baselines/reference/controlFlowBinaryOrExpression.types @@ -106,7 +106,7 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { sourceObj.length; >sourceObj.length : number ->sourceObj : NodeList +>sourceObj : NodeList | HTMLCollection >length : number } From 25af351014236059030ed4bc6b1c8aec2eee8978 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Oct 2017 12:50:01 -0700 Subject: [PATCH 5/8] Nix getBestChoiceType, [] subtyping, nominal union reduction for classes --- src/compiler/checker.ts | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 058cff4d8b664..146be93c5d59f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7434,8 +7434,8 @@ namespace ts { function isSubtypeOfAny(source: Type, targets: Type[]): boolean { for (const target of targets) { if (source !== target && isTypeSubtypeOf(source, target) && ( - !(getObjectFlags(source) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) || - !(getObjectFlags(target) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) || + !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) || + !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) || isTypeDerivedFrom(source, target))) { return true; } @@ -9605,7 +9605,7 @@ namespace ts { if (relation === identityRelation) { return propertiesIdenticalTo(source, target); } - const requireOptionalProperties = relation === subtypeRelation && !isObjectLiteralType(source); + const requireOptionalProperties = relation === subtypeRelation && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source); const unmatchedProperty = getUnmatchedProperty(source, target, requireOptionalProperties); if (unmatchedProperty) { if (reportErrors) { @@ -10313,6 +10313,11 @@ namespace ts { !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } + function isEmptyArrayLiteralType(type: Type): boolean { + const elementType = isArrayType(type) ? (type).typeArguments[0] : undefined; + return elementType === undefinedWideningType || elementType === neverType; + } + function isTupleLikeType(type: Type): boolean { return !!getPropertyOfType(type, "0" as __String); } @@ -13878,7 +13883,6 @@ namespace ts { type.pattern = node; return type; } - const contextualType = getApparentTypeOfContextualType(node); if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { const pattern = contextualType.pattern; // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting @@ -18066,14 +18070,6 @@ namespace ts { return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); } - function getBestChoiceType(type1: Type, type2: Type): Type { - const firstAssignableToSecond = isTypeAssignableTo(type1, type2); - const secondAssignableToFirst = isTypeAssignableTo(type2, type1); - return secondAssignableToFirst && !firstAssignableToSecond ? type1 : - firstAssignableToSecond && !secondAssignableToFirst ? type2 : - getUnionType([type1, type2], /*subtypeReduction*/ true); - } - function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) { return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); } @@ -18210,7 +18206,7 @@ namespace ts { leftType; case SyntaxKind.BarBarToken: return getTypeFacts(leftType) & TypeFacts.Falsy ? - getBestChoiceType(removeDefinitelyFalsyTypes(leftType), rightType) : + getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], /*subtypeReduction*/ true) : leftType; case SyntaxKind.EqualsToken: checkAssignmentOperator(rightType); @@ -18370,7 +18366,7 @@ namespace ts { checkExpression(node.condition); const type1 = checkExpression(node.whenTrue, checkMode); const type2 = checkExpression(node.whenFalse, checkMode); - return getBestChoiceType(type1, type2); + return getUnionType([type1, type2], /*subtypeReduction*/ true); } function checkTemplateExpression(node: TemplateExpression): Type { From 7f35c8fd07c10b7e964e82b4536b5fdc85be4e73 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Oct 2017 13:00:30 -0700 Subject: [PATCH 6/8] Add type annotation --- src/compiler/factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 65c1c92f36652..de744ca3f00f4 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2625,7 +2625,7 @@ namespace ts { /** * Gets a custom text range to use when emitting source maps. */ - export function getSourceMapRange(node: Node) { + export function getSourceMapRange(node: Node): SourceMapRange { const emitNode = node.emitNode; return (emitNode && emitNode.sourceMapRange) || node; } From 412f3735bc03a149dce28da1173ee2b5f8fa70cf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 31 Oct 2017 13:00:38 -0700 Subject: [PATCH 7/8] Accept new baselines --- .../reference/arrayBestCommonTypes.types | 32 +++++++++---------- .../controlFlowBinaryOrExpression.symbols | 4 +-- .../controlFlowBinaryOrExpression.types | 2 +- .../reference/fixSignatureCaching.types | 4 +-- .../nonContextuallyTypedLogicalOr.symbols | 4 +-- .../nonContextuallyTypedLogicalOr.types | 4 +-- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/baselines/reference/arrayBestCommonTypes.types b/tests/baselines/reference/arrayBestCommonTypes.types index c146a100d1881..864b1adfacba6 100644 --- a/tests/baselines/reference/arrayBestCommonTypes.types +++ b/tests/baselines/reference/arrayBestCommonTypes.types @@ -366,29 +366,29 @@ module EmptyTypes { >base2 : typeof base2 var b1 = [baseObj, base2Obj, ifaceObj]; ->b1 : (iface | base | base2)[] ->[baseObj, base2Obj, ifaceObj] : (iface | base | base2)[] +>b1 : iface[] +>[baseObj, base2Obj, ifaceObj] : iface[] >baseObj : base >base2Obj : base2 >ifaceObj : iface var b2 = [base2Obj, baseObj, ifaceObj]; ->b2 : (iface | base | base2)[] ->[base2Obj, baseObj, ifaceObj] : (iface | base | base2)[] +>b2 : iface[] +>[base2Obj, baseObj, ifaceObj] : iface[] >base2Obj : base2 >baseObj : base >ifaceObj : iface var b3 = [baseObj, ifaceObj, base2Obj]; ->b3 : (iface | base | base2)[] ->[baseObj, ifaceObj, base2Obj] : (iface | base | base2)[] +>b3 : iface[] +>[baseObj, ifaceObj, base2Obj] : iface[] >baseObj : base >ifaceObj : iface >base2Obj : base2 var b4 = [ifaceObj, baseObj, base2Obj]; ->b4 : (iface | base | base2)[] ->[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[] +>b4 : iface[] +>[ifaceObj, baseObj, base2Obj] : iface[] >ifaceObj : iface >baseObj : base >base2Obj : base2 @@ -769,29 +769,29 @@ module NonEmptyTypes { >base2 : typeof base2 var b1 = [baseObj, base2Obj, ifaceObj]; ->b1 : (iface | base | base2)[] ->[baseObj, base2Obj, ifaceObj] : (iface | base | base2)[] +>b1 : iface[] +>[baseObj, base2Obj, ifaceObj] : iface[] >baseObj : base >base2Obj : base2 >ifaceObj : iface var b2 = [base2Obj, baseObj, ifaceObj]; ->b2 : (iface | base | base2)[] ->[base2Obj, baseObj, ifaceObj] : (iface | base | base2)[] +>b2 : iface[] +>[base2Obj, baseObj, ifaceObj] : iface[] >base2Obj : base2 >baseObj : base >ifaceObj : iface var b3 = [baseObj, ifaceObj, base2Obj]; ->b3 : (iface | base | base2)[] ->[baseObj, ifaceObj, base2Obj] : (iface | base | base2)[] +>b3 : iface[] +>[baseObj, ifaceObj, base2Obj] : iface[] >baseObj : base >ifaceObj : iface >base2Obj : base2 var b4 = [ifaceObj, baseObj, base2Obj]; ->b4 : (iface | base | base2)[] ->[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[] +>b4 : iface[] +>[ifaceObj, baseObj, base2Obj] : iface[] >ifaceObj : iface >baseObj : base >base2Obj : base2 diff --git a/tests/baselines/reference/controlFlowBinaryOrExpression.symbols b/tests/baselines/reference/controlFlowBinaryOrExpression.symbols index e76cfbf4caba9..5251973005fcd 100644 --- a/tests/baselines/reference/controlFlowBinaryOrExpression.symbols +++ b/tests/baselines/reference/controlFlowBinaryOrExpression.symbols @@ -86,8 +86,8 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) sourceObj.length; ->sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33)) +>sourceObj.length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27)) >sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3)) ->length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33)) +>length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27)) } diff --git a/tests/baselines/reference/controlFlowBinaryOrExpression.types b/tests/baselines/reference/controlFlowBinaryOrExpression.types index 8a3b8a6d055bb..e843844ebf1e4 100644 --- a/tests/baselines/reference/controlFlowBinaryOrExpression.types +++ b/tests/baselines/reference/controlFlowBinaryOrExpression.types @@ -106,7 +106,7 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { sourceObj.length; >sourceObj.length : number ->sourceObj : NodeList | HTMLCollection +>sourceObj : NodeList >length : number } diff --git a/tests/baselines/reference/fixSignatureCaching.types b/tests/baselines/reference/fixSignatureCaching.types index 6f87f563707b0..781912544e25d 100644 --- a/tests/baselines/reference/fixSignatureCaching.types +++ b/tests/baselines/reference/fixSignatureCaching.types @@ -866,9 +866,9 @@ define(function () { >'UnknownMobile' : "UnknownMobile" isArray = ('isArray' in Array) ? ->isArray = ('isArray' in Array) ? Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (value: any) => boolean +>isArray = ('isArray' in Array) ? Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (arg: any) => arg is any[] >isArray : any ->('isArray' in Array) ? Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (value: any) => boolean +>('isArray' in Array) ? Array.isArray : function (value) { return Object.prototype.toString.call(value) === '[object Array]'; } : (arg: any) => arg is any[] >('isArray' in Array) : boolean >'isArray' in Array : boolean >'isArray' : "isArray" diff --git a/tests/baselines/reference/nonContextuallyTypedLogicalOr.symbols b/tests/baselines/reference/nonContextuallyTypedLogicalOr.symbols index 43d7539b6b9b6..2d921f6631c23 100644 --- a/tests/baselines/reference/nonContextuallyTypedLogicalOr.symbols +++ b/tests/baselines/reference/nonContextuallyTypedLogicalOr.symbols @@ -28,8 +28,8 @@ var e: Ellement; >Ellement : Symbol(Ellement, Decl(nonContextuallyTypedLogicalOr.ts, 3, 1)) (c || e).dummy; ->(c || e).dummy : Symbol(Contextual.dummy, Decl(nonContextuallyTypedLogicalOr.ts, 0, 22)) +>(c || e).dummy : Symbol(dummy, Decl(nonContextuallyTypedLogicalOr.ts, 0, 22), Decl(nonContextuallyTypedLogicalOr.ts, 5, 20)) >c : Symbol(c, Decl(nonContextuallyTypedLogicalOr.ts, 10, 3)) >e : Symbol(e, Decl(nonContextuallyTypedLogicalOr.ts, 11, 3)) ->dummy : Symbol(Contextual.dummy, Decl(nonContextuallyTypedLogicalOr.ts, 0, 22)) +>dummy : Symbol(dummy, Decl(nonContextuallyTypedLogicalOr.ts, 0, 22), Decl(nonContextuallyTypedLogicalOr.ts, 5, 20)) diff --git a/tests/baselines/reference/nonContextuallyTypedLogicalOr.types b/tests/baselines/reference/nonContextuallyTypedLogicalOr.types index 5061ad1d9758b..aeb9d1409c6e6 100644 --- a/tests/baselines/reference/nonContextuallyTypedLogicalOr.types +++ b/tests/baselines/reference/nonContextuallyTypedLogicalOr.types @@ -29,8 +29,8 @@ var e: Ellement; (c || e).dummy; >(c || e).dummy : any ->(c || e) : Contextual ->c || e : Contextual +>(c || e) : Contextual | Ellement +>c || e : Contextual | Ellement >c : Contextual >e : Ellement >dummy : any From 81326ac90178a5a481412dab32fc458cb45be4e5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Nov 2017 09:16:16 -0700 Subject: [PATCH 8/8] Properly handle Object and Function types --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9cd21263b8dda..1fd70a22b677a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8571,14 +8571,16 @@ namespace ts { // An object type S is considered to be derived from an object type T if // S is a union type and every constituent of S is derived from T, // T is a union type and S is derived from at least one constituent of T, or + // T is one of the global types Object and Function and S is a subtype of T, or // T occurs directly or indirectly in an 'extends' clause of S. // Note that this check ignores type parameters and only considers the // inheritance hierarchy. function isTypeDerivedFrom(source: Type, target: Type): boolean { return source.flags & TypeFlags.Union ? every((source).types, t => isTypeDerivedFrom(t, target)) : target.flags & TypeFlags.Union ? some((target).types, t => isTypeDerivedFrom(source, t)) : + target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) : hasBaseType(source, getTargetType(target)); - } + } /** * This is *not* a bi-directional relationship.