Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce intersections by discriminants #36696

Merged
merged 35 commits into from
Feb 29, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ace0904
Treat never-like intersections as never
ahejlsberg Feb 8, 2020
eaf872c
Accept new baselines
ahejlsberg Feb 8, 2020
94353d2
Fix compiler issues revealed by increased intersection correctness
ahejlsberg Feb 8, 2020
346ec30
Delete fourslash tests that are no longer applicable
ahejlsberg Feb 8, 2020
acd3fec
Include isNeverLikeIntersection check in getNormalizedType
ahejlsberg Feb 9, 2020
7ae4a21
Erase never-like types in several more places
ahejlsberg Feb 10, 2020
3a1ba48
Check that base types are not never-like
ahejlsberg Feb 10, 2020
e1434a5
Add comments
ahejlsberg Feb 10, 2020
37c6280
Revert isNeverLikeType check in getIndexType (keyof shouldn't resolve…
ahejlsberg Feb 10, 2020
dba1043
Introduce getReducedType for union and intersection types
ahejlsberg Feb 11, 2020
f170191
Don't reduce in getApparentType
ahejlsberg Feb 11, 2020
6b2f3a2
Avoid relationship check in resolveMappedTypeMembers
ahejlsberg Feb 12, 2020
aeab6af
Merge branch 'master' into neverLikeIntersections
ahejlsberg Feb 12, 2020
4f67910
Accept new baselines
ahejlsberg Feb 12, 2020
49302f2
Don't call getReducedType in getIndexType
ahejlsberg Feb 13, 2020
aa8d227
Ensure reduced and unreduced forms of a type can compare identical
ahejlsberg Feb 14, 2020
8907e92
Reduce types before converting them to string representation
ahejlsberg Feb 15, 2020
04facee
Accept new baselines
ahejlsberg Feb 15, 2020
88be5ea
Reduce intersections before obtaining keyof X
ahejlsberg Feb 17, 2020
fbf13dc
Add tests
ahejlsberg Feb 17, 2020
85447a5
Accept new baselines
ahejlsberg Feb 17, 2020
7741085
Fix comment in tests
ahejlsberg Feb 18, 2020
d2b3807
Don't infer from empty intersection types
ahejlsberg Feb 22, 2020
6590e20
Add tests
ahejlsberg Feb 22, 2020
40340ae
Accept new baselines
ahejlsberg Feb 22, 2020
c4c1418
Defer instantiation of mapped type property types
ahejlsberg Feb 24, 2020
8eb08e8
Accept new baselines
ahejlsberg Feb 24, 2020
874938c
Merge branch 'master' into neverLikeIntersections
ahejlsberg Feb 24, 2020
ede9d01
Include more precise type in diagnostic
ahejlsberg Feb 24, 2020
42022f3
Accept new baselines
ahejlsberg Feb 24, 2020
e24b250
Minor optimization
ahejlsberg Feb 25, 2020
12f6224
Merge branch 'master' into neverLikeIntersections
ahejlsberg Feb 25, 2020
a015ab9
Improve error message
ahejlsberg Feb 25, 2020
95ecb7b
Merge branch 'master' into neverLikeIntersections
ahejlsberg Feb 26, 2020
b99b9b2
Optional properties in intersections are never discriminants
ahejlsberg Feb 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 67 additions & 20 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1795,9 +1795,7 @@ namespace ts {

const target = getTargetOfBindingOrAssignmentElement(bindingElement);
if (target && isPropertyName(target)) {
return isComputedPropertyName(target) && isStringOrNumericLiteral(target.expression)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? Related?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what your question is here? With the improved precision of intersections, the checker was proving that this expression could never be true.

? target.expression
: target;
return target;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/classFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ namespace ts {
);
}

function visitArrayAssignmentTarget(node: AssignmentPattern) {
function visitArrayAssignmentTarget(node: BindingOrAssignmentElement) {
const target = getTargetOfBindingOrAssignmentElement(node);
if (target && isPrivateIdentifierPropertyAccessExpression(target)) {
const wrapped = wrapPrivateIdentifierForDestructuringTarget(target);
Expand Down
17 changes: 13 additions & 4 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4131,6 +4131,7 @@ namespace ts {
OptionalParameter = 1 << 14, // Optional parameter
RestParameter = 1 << 15, // Rest parameter
DeferredType = 1 << 16, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
HasNeverType = 1 << 17, // Synthetic property with at least one never type in constituents
Synthetic = SyntheticProperty | SyntheticMethod,
Discriminant = HasNonUniformType | HasLiteralType,
Partial = ReadPartial | WritePartial
Expand Down Expand Up @@ -4338,16 +4339,16 @@ namespace ts {
NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable,
// The following flags are aggregated during union and intersection type construction
/* @internal */
IncludesMask = Any | Unknown | Primitive | Never | Object | Union | NonPrimitive,
IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive,
// The following flags are used for different purposes during union and intersection type construction
/* @internal */
IncludesStructuredOrInstantiable = TypeParameter,
/* @internal */
IncludesNonWideningType = Intersection,
IncludesNonWideningType = Index,
/* @internal */
IncludesWildcard = Index,
IncludesWildcard = IndexedAccess,
/* @internal */
IncludesEmptyObject = IndexedAccess,
IncludesEmptyObject = Conditional,
}

export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
Expand Down Expand Up @@ -4459,6 +4460,12 @@ namespace ts {
IsGenericIndexTypeComputed = 1 << 24, // IsGenericIndexType flag has been computed
/* @internal */
IsGenericIndexType = 1 << 25, // Union or intersection contains generic index type
/* @internal */
ContainsIntersections = 1 << 26, // Union contains intersections
/* @internal */
IsNeverIntersectionComputed = 1 << 26, // IsNeverLike flag has been computed
/* @internal */
IsNeverIntersection = 1 << 27, // Intersection reduces to never
ClassOrInterface = Class | Interface,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,
Expand Down Expand Up @@ -4582,6 +4589,8 @@ namespace ts {
}

export interface UnionType extends UnionOrIntersectionType {
/* @internal */
resolvedReducedType: Type;
}

export interface IntersectionType extends UnionOrIntersectionType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ class C<T extends Options> {
>method : () => void

let { a, b } = this.foo;
>a : T["a"]
>a : T["a"] | undefined
>b : T["b"]
>this.foo : { [P in keyof T]: T[P]; }
>this : this
>foo : { [P in keyof T]: T[P]; }

!(a && b);
>!(a && b) : false
>(a && b) : T["b"]
>a && b : T["b"]
>a : T["a"]
>!(a && b) : boolean
>(a && b) : T["b"] | undefined
>a && b : T["b"] | undefined
>a : T["a"] | undefined
>b : T["b"]

a;
>a : T["a"]
>a : T["a"] | undefined
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(27,30): error TS
Object literal may only specify known properties, and 'c' does not exist in type '{ a: null; b: string; }'.
tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(32,11): error TS2339: Property 'b' does not exist on type '{ a: 0; b: string; } | { a: T; c: number; }'.
Property 'b' does not exist on type '{ a: T; c: number; }'.
tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(132,11): error TS2339: Property 'value' does not exist on type 'never'.


==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (3 errors) ====
==== tests/cases/conformance/types/union/discriminatedUnionTypes2.ts (2 errors) ====
function f10(x : { kind: false, a: string } | { kind: true, b: string } | { kind: string, c: string }) {
if (x.kind === false) {
x.a;
Expand Down Expand Up @@ -144,8 +143,6 @@ tests/cases/conformance/types/union/discriminatedUnionTypes2.ts(132,11): error T
}
else {
x.value; // Error, x is never

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an error anymore, it seems

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an expected effect. After reducing away empty intersections, x is no longer a union type and therefore we don't do control flow based narrowing. It is similar to what you'd see if x just had the type { type: number, value: number }.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that the comment is outdated now

~~~~~
!!! error TS2339: Property 'value' does not exist on type 'never'.
}
}

Expand Down
14 changes: 8 additions & 6 deletions tests/baselines/reference/discriminatedUnionTypes2.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,9 @@ function f(problem: abc & (b | c)) {
>c : Symbol(c, Decl(discriminatedUnionTypes2.ts, 104, 1))

if (problem.type === 'b') {
>problem.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10), Decl(discriminatedUnionTypes2.ts, 97, 10), Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 97, 10) ... and 5 more)
>problem.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10))
>problem : Symbol(problem, Decl(discriminatedUnionTypes2.ts, 112, 11))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10), Decl(discriminatedUnionTypes2.ts, 97, 10), Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 97, 10) ... and 5 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 101, 10), Decl(discriminatedUnionTypes2.ts, 105, 10))

problem.name;
>problem.name : Symbol(name, Decl(discriminatedUnionTypes2.ts, 102, 14))
Expand Down Expand Up @@ -356,9 +356,9 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 126, 33))

if (x.type === 'number') {
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 124, 7) ... and 1 more)
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 126, 14))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 126, 33), Decl(discriminatedUnionTypes2.ts, 124, 7) ... and 1 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 126, 33))

x.value; // number
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
Expand All @@ -367,7 +367,9 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
}
else {
x.value; // Error, x is never
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 126, 14))
>value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
}
}

Expand All @@ -379,9 +381,9 @@ function foo2(x: RuntimeValue & ({ type: 'number' } | { type: 'string' })) {
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 135, 55))

if (x.type === 'number') {
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 55), Decl(discriminatedUnionTypes2.ts, 123, 7) ... and 7 more)
>x.type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 135, 55))
>x : Symbol(x, Decl(discriminatedUnionTypes2.ts, 135, 14))
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 55), Decl(discriminatedUnionTypes2.ts, 123, 7) ... and 7 more)
>type : Symbol(type, Decl(discriminatedUnionTypes2.ts, 122, 7), Decl(discriminatedUnionTypes2.ts, 135, 34), Decl(discriminatedUnionTypes2.ts, 123, 7), Decl(discriminatedUnionTypes2.ts, 135, 55))

x.value; // number
>x.value : Symbol(value, Decl(discriminatedUnionTypes2.ts, 122, 23))
Expand Down
24 changes: 12 additions & 12 deletions tests/baselines/reference/discriminatedUnionTypes2.types
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,13 @@ type abc = a | b | c;
>abc : abc

function f(problem: abc & (b | c)) {
>f : (problem: b | c | (a & b) | (a & c) | (b & c) | (c & b)) => void
>problem : b | c | (a & b) | (a & c) | (b & c) | (c & b)
>f : (problem: b | c) => void
>problem : b | c

if (problem.type === 'b') {
>problem.type === 'b' : boolean
>problem.type : "b" | "c"
>problem : b | c | (a & b) | (a & c) | (b & c) | (c & b)
>problem : b | c
>type : "b" | "c"
>'b' : "b"

Expand Down Expand Up @@ -362,14 +362,14 @@ type RuntimeValue =
>value : boolean

function foo1(x: RuntimeValue & { type: 'number' }) {
>foo1 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })
>foo1 : (x: { type: "number"; value: number; } & { type: "number"; }) => void
>x : { type: "number"; value: number; } & { type: "number"; }
>type : "number"

if (x.type === 'number') {
>x.type === 'number' : boolean
>x.type : "number"
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; })
>x : { type: "number"; value: number; } & { type: "number"; }
>type : "number"
>'number' : "number"

Expand All @@ -380,22 +380,22 @@ function foo1(x: RuntimeValue & { type: 'number' }) {
}
else {
x.value; // Error, x is never
>x.value : any
>x : never
>value : any
>x.value : number
>x : { type: "number"; value: number; } & { type: "number"; }
>value : number
}
}

function foo2(x: RuntimeValue & ({ type: 'number' } | { type: 'string' })) {
>foo2 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })
>foo2 : (x: ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })) => void
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })
>type : "number"
>type : "string"

if (x.type === 'number') {
>x.type === 'number' : boolean
>x.type : "string" | "number"
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "number"; value: number; } & { type: "string"; }) | ({ type: "string"; value: string; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; }) | ({ type: "boolean"; value: boolean; } & { type: "number"; }) | ({ type: "boolean"; value: boolean; } & { type: "string"; })
>x : ({ type: "number"; value: number; } & { type: "number"; }) | ({ type: "string"; value: string; } & { type: "string"; })
>type : "string" | "number"
>'number' : "number"

Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/objectSpread.types
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ let overwriteId: { id: string, a: number, c: number, d: string } =
>d : string

f({ a: 1, id: true }, { c: 1, d: 'no' })
>f({ a: 1, id: true }, { c: 1, d: 'no' }) : { a: number; id: boolean; } & { c: number; d: string; } & { id: string; }
>f({ a: 1, id: true }, { c: 1, d: 'no' }) : never
>f : <T, U>(t: T, u: U) => T & U & { id: string; }
>{ a: 1, id: true } : { a: number; id: true; }
>a : number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ class Test<T extends A> {
this.attrs.params!.name;
>this.attrs.params!.name : any
>this.attrs.params! : T["params"]
>this.attrs.params : T["params"]
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
>attrs : Readonly<T>
>params : T["params"]
>params : T["params"] | undefined
>name : any
}
}
Expand Down Expand Up @@ -66,10 +66,10 @@ class Test2<T extends A> {

return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
>this.attrs.params! : T["params"]
>this.attrs.params : T["params"]
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
>attrs : Readonly<T>
>params : T["params"]
>params : T["params"] | undefined
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ class Test<T extends A> {
this.attrs.params!.name;
>this.attrs.params!.name : string
>this.attrs.params! : NonNullable<T["params"]>
>this.attrs.params : T["params"]
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
>attrs : Readonly<T>
>params : T["params"]
>params : T["params"] | undefined
>name : string
}
}
Expand Down Expand Up @@ -63,10 +63,10 @@ class Test2<T extends A> {

return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
>this.attrs.params! : NonNullable<T["params"]>
>this.attrs.params : T["params"]
>this.attrs.params : T["params"] | undefined
>this.attrs : Readonly<T>
>this : this
>attrs : Readonly<T>
>params : T["params"]
>params : T["params"] | undefined
}
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/stringLiteralTypesAsTags01.types
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/stringLiteralTypesAsTags02.types
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/stringLiteralTypesAsTags03.types
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ if (!hasKind(x, "B")) {
}
else {
let d = x;
>d : A & B
>x : A & B
>d : never
>x : never
}
3 changes: 1 addition & 2 deletions tests/baselines/reference/tsxUnionElementType1.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ tests/cases/conformance/jsx/file.tsx(12,10): error TS2322: Type 'true' is not as
var SFCComp = SFC1 || SFC2;
<SFCComp x />
~
!!! error TS2322: Type 'true' is not assignable to type 'never'.
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:3:23: The expected type comes from property 'x' which is declared here on type 'IntrinsicAttributes & { x: number; } & { x: boolean; }'
!!! error TS2322: Type 'true' is not assignable to type 'never'.
3 changes: 1 addition & 2 deletions tests/baselines/reference/tsxUnionElementType2.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ tests/cases/conformance/jsx/file.tsx(12,10): error TS2322: Type 'string' is not
var SFCComp = SFC1 || SFC2;
<SFCComp x={"hi"}/>
~
!!! error TS2322: Type 'string' is not assignable to type 'never'.
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:3:23: The expected type comes from property 'x' which is declared here on type 'IntrinsicAttributes & { x: number; } & { x: boolean; }'
!!! error TS2322: Type 'string' is not assignable to type 'never'.
14 changes: 14 additions & 0 deletions tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'.


==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
interface I { global: string; }
var result: I;
var result2: I;

if (!(result instanceof RegExp)) {
result = result2;
} else if (!result.global) {
~~~~~~
!!! error TS2339: Property 'global' does not exist on type 'never'.
}
2 changes: 0 additions & 2 deletions tests/baselines/reference/typeGuardsWithInstanceOf.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@ if (!(result instanceof RegExp)) {
>result2 : Symbol(result2, Decl(typeGuardsWithInstanceOf.ts, 2, 3))

} else if (!result.global) {
>result.global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.es5.d.ts, --, --))
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
>global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.es5.d.ts, --, --))
}
6 changes: 3 additions & 3 deletions tests/baselines/reference/typeGuardsWithInstanceOf.types
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ if (!(result instanceof RegExp)) {

} else if (!result.global) {
>!result.global : boolean
>result.global : never
>result : I & RegExp
>global : never
>result.global : any
>result : never
>global : any
}
6 changes: 3 additions & 3 deletions tests/baselines/reference/typeVariableTypeGuards.types
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class A<P extends Partial<Foo>> {
>doSomething : () => void

this.props.foo && this.props.foo()
>this.props.foo && this.props.foo() : void
>this.props.foo : P["foo"]
>this.props.foo && this.props.foo() : void | undefined
>this.props.foo : P["foo"] | undefined
>this.props : Readonly<P>
>this : this
>props : Readonly<P>
>foo : P["foo"]
>foo : P["foo"] | undefined
>this.props.foo() : void
>this.props.foo : () => void
>this.props : Readonly<P>
Expand Down
Loading