Merge branch 'master' into fixNarrowingWithAny

This commit is contained in:
Mohamed Hegazy 2016-09-12 14:07:34 -07:00
commit 208b341733
7 changed files with 151 additions and 2 deletions

View file

@ -8732,7 +8732,7 @@ namespace ts {
// type. Otherwise, the types are completely unrelated, so narrow to an intersection of the
// two types.
const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
return isTypeSubtypeOf(candidate, targetType) ? candidate :
return isTypeSubtypeOf(candidate, type) ? candidate :
isTypeAssignableTo(type, candidate) ? type :
isTypeAssignableTo(candidate, targetType) ? candidate :
getIntersectionType([type, candidate]);

View file

@ -294,6 +294,7 @@ namespace ts {
"classic": ModuleResolutionKind.Classic,
}),
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
paramType: Diagnostics.STRATEGY,
},
{
name: "allowUnusedLabels",

View file

@ -2464,6 +2464,10 @@
"category": "Message",
"code": 6038
},
"STRATEGY": {
"category": "Message",
"code": 6039
},
"Compilation complete. Watching for file changes.": {
"category": "Message",
"code": 6042
@ -2863,7 +2867,7 @@
"Element implicitly has an 'any' type because index expression is not of type 'number'.": {
"category": "Error",
"code": 7015
},
},
"Index signature of object type implicitly has an 'any' type.": {
"category": "Error",
"code": 7017

View file

@ -0,0 +1,32 @@
//// [narrowingConstrainedTypeParameter.ts]
// Repro from #10811
interface Pet {
name: string;
}
function isPet(pet: any): pet is Pet {
return typeof pet.name === "string";
}
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
if (!isPet(pet)) {
throw new Error("Expected \"pet\" to be a Pet");
}
return voice(pet);
}
//// [narrowingConstrainedTypeParameter.js]
// Repro from #10811
"use strict";
function isPet(pet) {
return typeof pet.name === "string";
}
function speak(pet, voice) {
if (!isPet(pet)) {
throw new Error("Expected \"pet\" to be a Pet");
}
return voice(pet);
}
exports.speak = speak;

View file

@ -0,0 +1,42 @@
=== tests/cases/compiler/narrowingConstrainedTypeParameter.ts ===
// Repro from #10811
interface Pet {
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
name: string;
>name : Symbol(Pet.name, Decl(narrowingConstrainedTypeParameter.ts, 3, 15))
}
function isPet(pet: any): pet is Pet {
>isPet : Symbol(isPet, Decl(narrowingConstrainedTypeParameter.ts, 5, 1))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
return typeof pet.name === "string";
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 7, 15))
}
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
>speak : Symbol(speak, Decl(narrowingConstrainedTypeParameter.ts, 9, 1))
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
>Pet : Symbol(Pet, Decl(narrowingConstrainedTypeParameter.ts, 0, 0))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
>voice : Symbol(voice, Decl(narrowingConstrainedTypeParameter.ts, 11, 50))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 59))
>TPet : Symbol(TPet, Decl(narrowingConstrainedTypeParameter.ts, 11, 22))
if (!isPet(pet)) {
>isPet : Symbol(isPet, Decl(narrowingConstrainedTypeParameter.ts, 5, 1))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
throw new Error("Expected \"pet\" to be a Pet");
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
}
return voice(pet);
>voice : Symbol(voice, Decl(narrowingConstrainedTypeParameter.ts, 11, 50))
>pet : Symbol(pet, Decl(narrowingConstrainedTypeParameter.ts, 11, 40))
}

View file

@ -0,0 +1,52 @@
=== tests/cases/compiler/narrowingConstrainedTypeParameter.ts ===
// Repro from #10811
interface Pet {
>Pet : Pet
name: string;
>name : string
}
function isPet(pet: any): pet is Pet {
>isPet : (pet: any) => pet is Pet
>pet : any
>pet : any
>Pet : Pet
return typeof pet.name === "string";
>typeof pet.name === "string" : boolean
>typeof pet.name : string
>pet.name : any
>pet : any
>name : any
>"string" : "string"
}
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
>speak : <TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string) => string
>TPet : TPet
>Pet : Pet
>pet : TPet
>TPet : TPet
>voice : (pet: TPet) => string
>pet : TPet
>TPet : TPet
if (!isPet(pet)) {
>!isPet(pet) : boolean
>isPet(pet) : boolean
>isPet : (pet: any) => pet is Pet
>pet : TPet
throw new Error("Expected \"pet\" to be a Pet");
>new Error("Expected \"pet\" to be a Pet") : Error
>Error : ErrorConstructor
>"Expected \"pet\" to be a Pet" : "Expected \"pet\" to be a Pet"
}
return voice(pet);
>voice(pet) : string
>voice : (pet: TPet) => string
>pet : TPet
}

View file

@ -0,0 +1,18 @@
// @strictNullChecks: true
// Repro from #10811
interface Pet {
name: string;
}
function isPet(pet: any): pet is Pet {
return typeof pet.name === "string";
}
export function speak<TPet extends Pet>(pet: TPet, voice: (pet: TPet) => string): string {
if (!isPet(pet)) {
throw new Error("Expected \"pet\" to be a Pet");
}
return voice(pet);
}