Skip to content

Commit 208b341

Browse files
committed
Merge branch 'master' into fixNarrowingWithAny
2 parents 1973cf8 + b526aa3 commit 208b341

File tree

7 files changed

+151
-2
lines changed

7 files changed

+151
-2
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8732,7 +8732,7 @@ namespace ts {
87328732
// type. Otherwise, the types are completely unrelated, so narrow to an intersection of the
87338733
// two types.
87348734
const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
8735-
return isTypeSubtypeOf(candidate, targetType) ? candidate :
8735+
return isTypeSubtypeOf(candidate, type) ? candidate :
87368736
isTypeAssignableTo(type, candidate) ? type :
87378737
isTypeAssignableTo(candidate, targetType) ? candidate :
87388738
getIntersectionType([type, candidate]);

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ namespace ts {
294294
"classic": ModuleResolutionKind.Classic,
295295
}),
296296
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
297+
paramType: Diagnostics.STRATEGY,
297298
},
298299
{
299300
name: "allowUnusedLabels",

src/compiler/diagnosticMessages.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2464,6 +2464,10 @@
24642464
"category": "Message",
24652465
"code": 6038
24662466
},
2467+
"STRATEGY": {
2468+
"category": "Message",
2469+
"code": 6039
2470+
},
24672471
"Compilation complete. Watching for file changes.": {
24682472
"category": "Message",
24692473
"code": 6042
@@ -2863,7 +2867,7 @@
28632867
"Element implicitly has an 'any' type because index expression is not of type 'number'.": {
28642868
"category": "Error",
28652869
"code": 7015
2866-
},
2870+
},
28672871
"Index signature of object type implicitly has an 'any' type.": {
28682872
"category": "Error",
28692873
"code": 7017
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [narrowingConstrainedTypeParameter.ts]
2+
3+
// Repro from #10811
4+
5+
interface Pet {
6+
name: string;
7+
}
8+
9+
function isPet(pet: any): pet is Pet {
10+
return typeof pet.name === "string";
11+
}
12+
13+
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
14+
if (!isPet(pet)) {
15+
throw new Error("Expected \"pet\" to be a Pet");
16+
}
17+
return voice(pet);
18+
}
19+
20+
//// [narrowingConstrainedTypeParameter.js]
21+
// Repro from #10811
22+
"use strict";
23+
function isPet(pet) {
24+
return typeof pet.name === "string";
25+
}
26+
function speak(pet, voice) {
27+
if (!isPet(pet)) {
28+
throw new Error("Expected \"pet\" to be a Pet");
29+
}
30+
return voice(pet);
31+
}
32+
exports.speak = speak;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/narrowingConstrainedTypeParameter.ts ===
2+
3+
// Repro from #10811
4+
5+
interface Pet {
6+
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
7+
8+
name: string;
9+
>name : Symbol(Pet.name, Decl(narrowingConstrainedTypeParameter.ts, 3, 15))
10+
}
11+
12+
function isPet(pet: any): pet is Pet {
13+
>isPet : Symbol(isPet, Decl(narrowingConstrainedTypeParameter.ts, 5, 1))
14+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
15+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
16+
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
17+
18+
return typeof pet.name === "string";
19+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
20+
}
21+
22+
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
23+
>speak : Symbol(speak, Decl(narrowingConstrainedTypeParameter.ts, 9, 1))
24+
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
25+
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
26+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
27+
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
28+
>voice : Symbol(voice, Decl(narrowingConstrainedTypeParameter.ts, 11, 50))
29+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 59))
30+
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
31+
32+
if (!isPet(pet)) {
33+
>isPet : Symbol(isPet, Decl(narrowingConstrainedTypeParameter.ts, 5, 1))
34+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
35+
36+
throw new Error("Expected \"pet\" to be a Pet");
37+
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
38+
}
39+
return voice(pet);
40+
>voice : Symbol(voice, Decl(narrowingConstrainedTypeParameter.ts, 11, 50))
41+
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
42+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
=== tests/cases/compiler/narrowingConstrainedTypeParameter.ts ===
2+
3+
// Repro from #10811
4+
5+
interface Pet {
6+
>Pet : Pet
7+
8+
name: string;
9+
>name : string
10+
}
11+
12+
function isPet(pet: any): pet is Pet {
13+
>isPet : (pet: any) => pet is Pet
14+
>pet : any
15+
>pet : any
16+
>Pet : Pet
17+
18+
return typeof pet.name === "string";
19+
>typeof pet.name === "string" : boolean
20+
>typeof pet.name : string
21+
>pet.name : any
22+
>pet : any
23+
>name : any
24+
>"string" : "string"
25+
}
26+
27+
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
28+
>speak : <TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string) => string
29+
>TPet : TPet
30+
>Pet : Pet
31+
>pet : TPet
32+
>TPet : TPet
33+
>voice : (pet: TPet) => string
34+
>pet : TPet
35+
>TPet : TPet
36+
37+
if (!isPet(pet)) {
38+
>!isPet(pet) : boolean
39+
>isPet(pet) : boolean
40+
>isPet : (pet: any) => pet is Pet
41+
>pet : TPet
42+
43+
throw new Error("Expected \"pet\" to be a Pet");
44+
>new Error("Expected \"pet\" to be a Pet") : Error
45+
>Error : ErrorConstructor
46+
>"Expected \"pet\" to be a Pet" : "Expected \"pet\" to be a Pet"
47+
}
48+
return voice(pet);
49+
>voice(pet) : string
50+
>voice : (pet: TPet) => string
51+
>pet : TPet
52+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @strictNullChecks: true
2+
3+
// Repro from #10811
4+
5+
interface Pet {
6+
name: string;
7+
}
8+
9+
function isPet(pet: any): pet is Pet {
10+
return typeof pet.name === "string";
11+
}
12+
13+
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
14+
if (!isPet(pet)) {
15+
throw new Error("Expected \"pet\" to be a Pet");
16+
}
17+
return voice(pet);
18+
}

0 commit comments

Comments
 (0)