Skip to content

Commit 7a92282

Browse files
committed
Merge branch 'release-1.5' of https://github.com/Microsoft/TypeScript into removeSubtypesRecursion
2 parents bb7f617 + ebb5a0d commit 7a92282

13 files changed

+532
-39
lines changed

src/compiler/checker.ts

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,38 +5398,43 @@ module ts {
53985398
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
53995399
return type;
54005400
}
5401-
// Target type is type of prototype property
5401+
5402+
let targetType: Type;
54025403
let prototypeProperty = getPropertyOfType(rightType, "prototype");
54035404
if (prototypeProperty) {
5404-
let targetType = getTypeOfSymbol(prototypeProperty);
5405-
if (targetType !== anyType) {
5406-
// Narrow to the target type if it's a subtype of the current type
5407-
if (isTypeSubtypeOf(targetType, type)) {
5408-
return targetType;
5409-
}
5410-
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
5411-
if (type.flags & TypeFlags.Union) {
5412-
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
5413-
}
5405+
// Target type is type of the protoype property
5406+
let prototypePropertyType = getTypeOfSymbol(prototypeProperty);
5407+
if (prototypePropertyType !== anyType) {
5408+
targetType = prototypePropertyType;
54145409
}
54155410
}
5416-
// Target type is type of construct signature
5417-
let constructSignatures: Signature[];
5418-
if (rightType.flags & TypeFlags.Interface) {
5419-
constructSignatures = resolveDeclaredMembers(<InterfaceType>rightType).declaredConstructSignatures;
5420-
}
5421-
else if (rightType.flags & TypeFlags.Anonymous) {
5422-
constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
5411+
5412+
if (!targetType) {
5413+
// Target type is type of construct signature
5414+
let constructSignatures: Signature[];
5415+
if (rightType.flags & TypeFlags.Interface) {
5416+
constructSignatures = resolveDeclaredMembers(<InterfaceType>rightType).declaredConstructSignatures;
5417+
}
5418+
else if (rightType.flags & TypeFlags.Anonymous) {
5419+
constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
5420+
}
5421+
5422+
if (constructSignatures && constructSignatures.length) {
5423+
targetType = getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))));
5424+
}
54235425
}
54245426

5425-
if (constructSignatures && constructSignatures.length !== 0) {
5426-
let instanceType = getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))));
5427-
// Pickup type from union types
5427+
if (targetType) {
5428+
// Narrow to the target type if it's a subtype of the current type
5429+
if (isTypeSubtypeOf(targetType, type)) {
5430+
return targetType;
5431+
}
5432+
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
54285433
if (type.flags & TypeFlags.Union) {
5429-
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, instanceType)));
5434+
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
54305435
}
5431-
return instanceType;
54325436
}
5437+
54335438
return type;
54345439
}
54355440

src/lib/es6.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,6 +3580,7 @@ interface PromiseLike<T> {
35803580
* @returns A Promise for the completion of which ever callback is executed.
35813581
*/
35823582
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
3583+
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
35833584
}
35843585

35853586
/**
@@ -3593,6 +3594,7 @@ interface Promise<T> {
35933594
* @returns A Promise for the completion of which ever callback is executed.
35943595
*/
35953596
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>;
3597+
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>;
35963598

35973599
/**
35983600
* Attaches a callback for only the rejection of the Promise.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//// [narrowTypeByInstanceof.ts]
2+
class Match {
3+
public range(): any {
4+
return undefined;
5+
}
6+
}
7+
8+
class FileMatch {
9+
public resource(): any {
10+
return undefined;
11+
}
12+
}
13+
14+
type FileMatchOrMatch = FileMatch | Match;
15+
16+
17+
let elementA: FileMatchOrMatch, elementB: FileMatchOrMatch;
18+
19+
if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
20+
let a = elementA.resource().path;
21+
let b = elementB.resource().path;
22+
} else if (elementA instanceof Match && elementB instanceof Match) {
23+
let a = elementA.range();
24+
let b = elementB.range();
25+
}
26+
27+
28+
//// [narrowTypeByInstanceof.js]
29+
var Match = (function () {
30+
function Match() {
31+
}
32+
Match.prototype.range = function () {
33+
return undefined;
34+
};
35+
return Match;
36+
})();
37+
var FileMatch = (function () {
38+
function FileMatch() {
39+
}
40+
FileMatch.prototype.resource = function () {
41+
return undefined;
42+
};
43+
return FileMatch;
44+
})();
45+
var elementA, elementB;
46+
if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
47+
var a = elementA.resource().path;
48+
var b = elementB.resource().path;
49+
}
50+
else if (elementA instanceof Match && elementB instanceof Match) {
51+
var a = elementA.range();
52+
var b = elementB.range();
53+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
=== tests/cases/compiler/narrowTypeByInstanceof.ts ===
2+
class Match {
3+
>Match : Symbol(Match, Decl(narrowTypeByInstanceof.ts, 0, 0))
4+
5+
public range(): any {
6+
>range : Symbol(range, Decl(narrowTypeByInstanceof.ts, 0, 17))
7+
8+
return undefined;
9+
>undefined : Symbol(undefined)
10+
}
11+
}
12+
13+
class FileMatch {
14+
>FileMatch : Symbol(FileMatch, Decl(narrowTypeByInstanceof.ts, 4, 5))
15+
16+
public resource(): any {
17+
>resource : Symbol(resource, Decl(narrowTypeByInstanceof.ts, 6, 21))
18+
19+
return undefined;
20+
>undefined : Symbol(undefined)
21+
}
22+
}
23+
24+
type FileMatchOrMatch = FileMatch | Match;
25+
>FileMatchOrMatch : Symbol(FileMatchOrMatch, Decl(narrowTypeByInstanceof.ts, 10, 5))
26+
>FileMatch : Symbol(FileMatch, Decl(narrowTypeByInstanceof.ts, 4, 5))
27+
>Match : Symbol(Match, Decl(narrowTypeByInstanceof.ts, 0, 0))
28+
29+
30+
let elementA: FileMatchOrMatch, elementB: FileMatchOrMatch;
31+
>elementA : Symbol(elementA, Decl(narrowTypeByInstanceof.ts, 15, 3))
32+
>FileMatchOrMatch : Symbol(FileMatchOrMatch, Decl(narrowTypeByInstanceof.ts, 10, 5))
33+
>elementB : Symbol(elementB, Decl(narrowTypeByInstanceof.ts, 15, 31))
34+
>FileMatchOrMatch : Symbol(FileMatchOrMatch, Decl(narrowTypeByInstanceof.ts, 10, 5))
35+
36+
if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
37+
>elementA : Symbol(elementA, Decl(narrowTypeByInstanceof.ts, 15, 3))
38+
>FileMatch : Symbol(FileMatch, Decl(narrowTypeByInstanceof.ts, 4, 5))
39+
>elementB : Symbol(elementB, Decl(narrowTypeByInstanceof.ts, 15, 31))
40+
>FileMatch : Symbol(FileMatch, Decl(narrowTypeByInstanceof.ts, 4, 5))
41+
42+
let a = elementA.resource().path;
43+
>a : Symbol(a, Decl(narrowTypeByInstanceof.ts, 18, 7))
44+
>elementA.resource : Symbol(FileMatch.resource, Decl(narrowTypeByInstanceof.ts, 6, 21))
45+
>elementA : Symbol(elementA, Decl(narrowTypeByInstanceof.ts, 15, 3))
46+
>resource : Symbol(FileMatch.resource, Decl(narrowTypeByInstanceof.ts, 6, 21))
47+
48+
let b = elementB.resource().path;
49+
>b : Symbol(b, Decl(narrowTypeByInstanceof.ts, 19, 7))
50+
>elementB.resource : Symbol(FileMatch.resource, Decl(narrowTypeByInstanceof.ts, 6, 21))
51+
>elementB : Symbol(elementB, Decl(narrowTypeByInstanceof.ts, 15, 31))
52+
>resource : Symbol(FileMatch.resource, Decl(narrowTypeByInstanceof.ts, 6, 21))
53+
54+
} else if (elementA instanceof Match && elementB instanceof Match) {
55+
>elementA : Symbol(elementA, Decl(narrowTypeByInstanceof.ts, 15, 3))
56+
>Match : Symbol(Match, Decl(narrowTypeByInstanceof.ts, 0, 0))
57+
>elementB : Symbol(elementB, Decl(narrowTypeByInstanceof.ts, 15, 31))
58+
>Match : Symbol(Match, Decl(narrowTypeByInstanceof.ts, 0, 0))
59+
60+
let a = elementA.range();
61+
>a : Symbol(a, Decl(narrowTypeByInstanceof.ts, 21, 7))
62+
>elementA.range : Symbol(Match.range, Decl(narrowTypeByInstanceof.ts, 0, 17))
63+
>elementA : Symbol(elementA, Decl(narrowTypeByInstanceof.ts, 15, 3))
64+
>range : Symbol(Match.range, Decl(narrowTypeByInstanceof.ts, 0, 17))
65+
66+
let b = elementB.range();
67+
>b : Symbol(b, Decl(narrowTypeByInstanceof.ts, 22, 7))
68+
>elementB.range : Symbol(Match.range, Decl(narrowTypeByInstanceof.ts, 0, 17))
69+
>elementB : Symbol(elementB, Decl(narrowTypeByInstanceof.ts, 15, 31))
70+
>range : Symbol(Match.range, Decl(narrowTypeByInstanceof.ts, 0, 17))
71+
}
72+
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
=== tests/cases/compiler/narrowTypeByInstanceof.ts ===
2+
class Match {
3+
>Match : Match
4+
5+
public range(): any {
6+
>range : () => any
7+
8+
return undefined;
9+
>undefined : undefined
10+
}
11+
}
12+
13+
class FileMatch {
14+
>FileMatch : FileMatch
15+
16+
public resource(): any {
17+
>resource : () => any
18+
19+
return undefined;
20+
>undefined : undefined
21+
}
22+
}
23+
24+
type FileMatchOrMatch = FileMatch | Match;
25+
>FileMatchOrMatch : Match | FileMatch
26+
>FileMatch : FileMatch
27+
>Match : Match
28+
29+
30+
let elementA: FileMatchOrMatch, elementB: FileMatchOrMatch;
31+
>elementA : Match | FileMatch
32+
>FileMatchOrMatch : Match | FileMatch
33+
>elementB : Match | FileMatch
34+
>FileMatchOrMatch : Match | FileMatch
35+
36+
if (elementA instanceof FileMatch && elementB instanceof FileMatch) {
37+
>elementA instanceof FileMatch && elementB instanceof FileMatch : boolean
38+
>elementA instanceof FileMatch : boolean
39+
>elementA : Match | FileMatch
40+
>FileMatch : typeof FileMatch
41+
>elementB instanceof FileMatch : boolean
42+
>elementB : Match | FileMatch
43+
>FileMatch : typeof FileMatch
44+
45+
let a = elementA.resource().path;
46+
>a : any
47+
>elementA.resource().path : any
48+
>elementA.resource() : any
49+
>elementA.resource : () => any
50+
>elementA : FileMatch
51+
>resource : () => any
52+
>path : any
53+
54+
let b = elementB.resource().path;
55+
>b : any
56+
>elementB.resource().path : any
57+
>elementB.resource() : any
58+
>elementB.resource : () => any
59+
>elementB : FileMatch
60+
>resource : () => any
61+
>path : any
62+
63+
} else if (elementA instanceof Match && elementB instanceof Match) {
64+
>elementA instanceof Match && elementB instanceof Match : boolean
65+
>elementA instanceof Match : boolean
66+
>elementA : Match | FileMatch
67+
>Match : typeof Match
68+
>elementB instanceof Match : boolean
69+
>elementB : Match | FileMatch
70+
>Match : typeof Match
71+
72+
let a = elementA.range();
73+
>a : any
74+
>elementA.range() : any
75+
>elementA.range : () => any
76+
>elementA : Match
77+
>range : () => any
78+
79+
let b = elementB.range();
80+
>b : any
81+
>elementB.range() : any
82+
>elementB.range : () => any
83+
>elementB : Match
84+
>range : () => any
85+
}
86+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [promiseVoidErrorCallback.ts]
2+
interface T1 {
3+
__t1: string;
4+
}
5+
6+
interface T2 {
7+
__t2: string;
8+
}
9+
10+
interface T3 {
11+
__t3: string;
12+
}
13+
14+
function f1(): Promise<T1> {
15+
return Promise.resolve({ __t1: "foo_t1" });
16+
}
17+
18+
function f2(x: T1): T2 {
19+
return { __t2: x.__t1 + ":foo_21" };
20+
}
21+
22+
var x3 = f1()
23+
.then(f2, (e: Error) => {
24+
throw e;
25+
})
26+
.then((x: T2) => {
27+
return { __t3: x.__t2 + "bar" };
28+
});
29+
30+
//// [promiseVoidErrorCallback.js]
31+
function f1() {
32+
return Promise.resolve({ __t1: "foo_t1" });
33+
}
34+
function f2(x) {
35+
return { __t2: x.__t1 + ":foo_21" };
36+
}
37+
var x3 = f1()
38+
.then(f2, (e) => {
39+
throw e;
40+
})
41+
.then((x) => {
42+
return { __t3: x.__t2 + "bar" };
43+
});

0 commit comments

Comments
 (0)