Skip to content

Commit

Permalink
Revert "Revert "Merge pull request microsoft#7235 from weswigham/narr…
Browse files Browse the repository at this point in the history
…ow-all-types""

This reverts commit fc3e040.
  • Loading branch information
weswigham committed Jun 6, 2016
1 parent cd1b9f0 commit 9761c3b
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7664,7 +7664,7 @@ namespace ts {

function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
let key: string;
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
if (!reference.flowNode || assumeInitialized && (declaredType.flags & TypeFlags.NotNarrowable)) {
return declaredType;
}
const initialType = assumeInitialized ? declaredType : addNullableKind(declaredType, TypeFlags.Undefined);
Expand Down
8 changes: 7 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2218,7 +2218,13 @@ namespace ts {
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
Narrowable = Any | ObjectType | Union | TypeParameter,

// 'NotNarrowable' types are types where narrowing reverts to the original type, rather than actually narrow.
// This is never really correct - you can _always_ narrow to an intersection with that type, _but_ we keep
// Void as the only non-narrowable type, since it's a non-value type construct (representing a lack of a value)
// and, generally speaking, narrowing `void` should fail in some way, as it is nonsensical. (`void` narrowing
// to `void & T`, in a structural sense, is just narrowing to T, which we wouldn't allow under normal rules)
NotNarrowable = Void,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
Expand Down
38 changes: 38 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsPrimitiveIntersection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// [typeGuardNarrowsPrimitiveIntersection.ts]
type Tag = {__tag: any};
declare function isNonBlank(value: string) : value is (string & Tag);
declare function doThis(value: string & Tag): void;
declare function doThat(value: string) : void;
let value: string;
if (isNonBlank(value)) {
doThis(value);
} else {
doThat(value);
}


const enum Tag2 {}
declare function isNonBlank2(value: string) : value is (string & Tag2);
declare function doThis2(value: string & Tag2): void;
declare function doThat2(value: string) : void;
if (isNonBlank2(value)) {
doThis2(value);
} else {
doThat2(value);
}


//// [typeGuardNarrowsPrimitiveIntersection.js]
var value;
if (isNonBlank(value)) {
doThis(value);
}
else {
doThat(value);
}
if (isNonBlank2(value)) {
doThis2(value);
}
else {
doThat2(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsPrimitiveIntersection.ts ===
type Tag = {__tag: any};
>Tag : Symbol(Tag, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 0))
>__tag : Symbol(__tag, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 12))

declare function isNonBlank(value: string) : value is (string & Tag);
>isNonBlank : Symbol(isNonBlank, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 24))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 1, 28))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 1, 28))
>Tag : Symbol(Tag, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 0))

declare function doThis(value: string & Tag): void;
>doThis : Symbol(doThis, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 1, 69))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 2, 24))
>Tag : Symbol(Tag, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 0))

declare function doThat(value: string) : void;
>doThat : Symbol(doThat, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 2, 51))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 3, 24))

let value: string;
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))

if (isNonBlank(value)) {
>isNonBlank : Symbol(isNonBlank, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 0, 24))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))

doThis(value);
>doThis : Symbol(doThis, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 1, 69))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))

} else {
doThat(value);
>doThat : Symbol(doThat, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 2, 51))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))
}


const enum Tag2 {}
>Tag2 : Symbol(Tag2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 9, 1))

declare function isNonBlank2(value: string) : value is (string & Tag2);
>isNonBlank2 : Symbol(isNonBlank2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 12, 18))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 13, 29))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 13, 29))
>Tag2 : Symbol(Tag2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 9, 1))

declare function doThis2(value: string & Tag2): void;
>doThis2 : Symbol(doThis2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 13, 71))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 14, 25))
>Tag2 : Symbol(Tag2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 9, 1))

declare function doThat2(value: string) : void;
>doThat2 : Symbol(doThat2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 14, 53))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 15, 25))

if (isNonBlank2(value)) {
>isNonBlank2 : Symbol(isNonBlank2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 12, 18))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))

doThis2(value);
>doThis2 : Symbol(doThis2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 13, 71))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))

} else {
doThat2(value);
>doThat2 : Symbol(doThat2, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 14, 53))
>value : Symbol(value, Decl(typeGuardNarrowsPrimitiveIntersection.ts, 4, 3))
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsPrimitiveIntersection.ts ===
type Tag = {__tag: any};
>Tag : { __tag: any; }
>__tag : any

declare function isNonBlank(value: string) : value is (string & Tag);
>isNonBlank : (value: string) => value is string & { __tag: any; }
>value : string
>value : any
>Tag : { __tag: any; }

declare function doThis(value: string & Tag): void;
>doThis : (value: string & { __tag: any; }) => void
>value : string & { __tag: any; }
>Tag : { __tag: any; }

declare function doThat(value: string) : void;
>doThat : (value: string) => void
>value : string

let value: string;
>value : string

if (isNonBlank(value)) {
>isNonBlank(value) : boolean
>isNonBlank : (value: string) => value is string & { __tag: any; }
>value : string

doThis(value);
>doThis(value) : void
>doThis : (value: string & { __tag: any; }) => void
>value : string & { __tag: any; }

} else {
doThat(value);
>doThat(value) : void
>doThat : (value: string) => void
>value : string
}


const enum Tag2 {}
>Tag2 : Tag2

declare function isNonBlank2(value: string) : value is (string & Tag2);
>isNonBlank2 : (value: string) => value is string & Tag2
>value : string
>value : any
>Tag2 : Tag2

declare function doThis2(value: string & Tag2): void;
>doThis2 : (value: string & Tag2) => void
>value : string & Tag2
>Tag2 : Tag2

declare function doThat2(value: string) : void;
>doThat2 : (value: string) => void
>value : string

if (isNonBlank2(value)) {
>isNonBlank2(value) : boolean
>isNonBlank2 : (value: string) => value is string & Tag2
>value : string

doThis2(value);
>doThis2(value) : void
>doThis2 : (value: string & Tag2) => void
>value : string & Tag2

} else {
doThat2(value);
>doThat2(value) : void
>doThat2 : (value: string) => void
>value : string
}

21 changes: 21 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsToLiteralType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [typeGuardNarrowsToLiteralType.ts]
declare function isFoo(value: string) : value is "foo";
declare function doThis(value: "foo"): void;
declare function doThat(value: string) : void;
let value: string;
if (isFoo(value)) {
doThis(value);
} else {
doThat(value);
}



//// [typeGuardNarrowsToLiteralType.js]
var value;
if (isFoo(value)) {
doThis(value);
}
else {
doThat(value);
}
32 changes: 32 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsToLiteralType.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsToLiteralType.ts ===
declare function isFoo(value: string) : value is "foo";
>isFoo : Symbol(isFoo, Decl(typeGuardNarrowsToLiteralType.ts, 0, 0))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 0, 23))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 0, 23))

declare function doThis(value: "foo"): void;
>doThis : Symbol(doThis, Decl(typeGuardNarrowsToLiteralType.ts, 0, 55))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 1, 24))

declare function doThat(value: string) : void;
>doThat : Symbol(doThat, Decl(typeGuardNarrowsToLiteralType.ts, 1, 44))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 2, 24))

let value: string;
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 3, 3))

if (isFoo(value)) {
>isFoo : Symbol(isFoo, Decl(typeGuardNarrowsToLiteralType.ts, 0, 0))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 3, 3))

doThis(value);
>doThis : Symbol(doThis, Decl(typeGuardNarrowsToLiteralType.ts, 0, 55))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 3, 3))

} else {
doThat(value);
>doThat : Symbol(doThat, Decl(typeGuardNarrowsToLiteralType.ts, 1, 44))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralType.ts, 3, 3))
}


35 changes: 35 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsToLiteralType.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsToLiteralType.ts ===
declare function isFoo(value: string) : value is "foo";
>isFoo : (value: string) => value is "foo"
>value : string
>value : any

declare function doThis(value: "foo"): void;
>doThis : (value: "foo") => void
>value : "foo"

declare function doThat(value: string) : void;
>doThat : (value: string) => void
>value : string

let value: string;
>value : string

if (isFoo(value)) {
>isFoo(value) : boolean
>isFoo : (value: string) => value is "foo"
>value : string

doThis(value);
>doThis(value) : void
>doThis : (value: "foo") => void
>value : "foo"

} else {
doThat(value);
>doThat(value) : void
>doThat : (value: string) => void
>value : string
}


21 changes: 21 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsToLiteralTypeUnion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//// [typeGuardNarrowsToLiteralTypeUnion.ts]
declare function isFoo(value: string) : value is ("foo" | "bar");
declare function doThis(value: "foo" | "bar"): void;
declare function doThat(value: string) : void;
let value: string;
if (isFoo(value)) {
doThis(value);
} else {
doThat(value);
}



//// [typeGuardNarrowsToLiteralTypeUnion.js]
var value;
if (isFoo(value)) {
doThis(value);
}
else {
doThat(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsToLiteralTypeUnion.ts ===
declare function isFoo(value: string) : value is ("foo" | "bar");
>isFoo : Symbol(isFoo, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 0))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 23))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 23))

declare function doThis(value: "foo" | "bar"): void;
>doThis : Symbol(doThis, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 65))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 1, 24))

declare function doThat(value: string) : void;
>doThat : Symbol(doThat, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 1, 52))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 2, 24))

let value: string;
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 3, 3))

if (isFoo(value)) {
>isFoo : Symbol(isFoo, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 0))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 3, 3))

doThis(value);
>doThis : Symbol(doThis, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 0, 65))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 3, 3))

} else {
doThat(value);
>doThat : Symbol(doThat, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 1, 52))
>value : Symbol(value, Decl(typeGuardNarrowsToLiteralTypeUnion.ts, 3, 3))
}


35 changes: 35 additions & 0 deletions tests/baselines/reference/typeGuardNarrowsToLiteralTypeUnion.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardNarrowsToLiteralTypeUnion.ts ===
declare function isFoo(value: string) : value is ("foo" | "bar");
>isFoo : (value: string) => value is "foo" | "bar"
>value : string
>value : any

declare function doThis(value: "foo" | "bar"): void;
>doThis : (value: "foo" | "bar") => void
>value : "foo" | "bar"

declare function doThat(value: string) : void;
>doThat : (value: string) => void
>value : string

let value: string;
>value : string

if (isFoo(value)) {
>isFoo(value) : boolean
>isFoo : (value: string) => value is "foo" | "bar"
>value : string

doThis(value);
>doThis(value) : void
>doThis : (value: "foo" | "bar") => void
>value : "foo" | "bar"

} else {
doThat(value);
>doThat(value) : void
>doThat : (value: string) => void
>value : string
}


Loading

0 comments on commit 9761c3b

Please sign in to comment.