-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Labels
Breaking ChangeWould introduce errors in existing codeWould introduce errors in existing codeBugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
TypeScript Version: Nightly
Search Terms: intersection guard, intersection never
Expected behavior: In the first function, the type of obj
in the else
block is never
Actual behavior: In the first function, the type of obj
in the else
block is { str: string } & { num: number }
, the same as in the if
block.
Related Issues: I didn't find any.
Code
(obj: { str: string } & { num: number }) => {
// Non-Union Intersection type doesn't work as expected.
if ('str' in obj) {
const s: string = obj.str;
// obj: { str: string } & { num: number }
} else {
const _exhaustiveCheck: never = obj;
// Expected: No error. obj: never
// Actual: Type '{ str: string; } & { num: number; }' is not assignable to type 'never'.
}
};
(obj: { str: string; num: number }) => {
// Non-intersection type works as expected.
if ('str' in obj) {
const s: string = obj.str;
// obj: { str: string; num: number }
} else {
const _exhaustiveCheck: never = obj;
// No error. obj: never
}
};
(obj: { str: string } & { num: number } | { bool: boolean }) => {
// Union of intersection works as expected.
if ('str' in obj) {
const s: string = obj.str;
// obj: { str: string; num: number }
} else {
const proveIsBool: boolean = obj.bool;
// No error. obj: { bool: boolean }
}
};
Output
"use strict";
(obj) => {
// Non-Union Intersection type doesn't work as expected.
if ('str' in obj) {
const s = obj.str;
// obj: { str: string } & { num: number }
}
else {
const _exhaustiveCheck = obj;
// Expected: No error. obj: never
// Actual: Type '{ str: string; } & { num: number; }' is not assignable to type 'never'.
}
};
(obj) => {
// Non-intersection type works as expected.
if ('str' in obj) {
const s = obj.str;
// obj: { str: string; num: number }
}
else {
const _exhaustiveCheck = obj;
// No error. obj: never
}
};
(obj) => {
// Union of intersection works as expected.
if ('str' in obj) {
const s = obj.str;
// obj: { str: string; num: number }
}
else {
const proveIsBool = obj.bool;
// No error. obj: { bool: boolean }
}
};
Compiler Options
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"useDefineForClassFields": false,
"alwaysStrict": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"downlevelIteration": false,
"noEmitHelpers": false,
"noLib": false,
"noStrictGenericChecks": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"esModuleInterop": true,
"preserveConstEnums": false,
"removeComments": false,
"skipLibCheck": false,
"checkJs": false,
"allowJs": false,
"declaration": true,
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"target": "ES2017",
"module": "ESNext"
}
}
Playground Link: Provided
Metadata
Metadata
Assignees
Labels
Breaking ChangeWould introduce errors in existing codeWould introduce errors in existing codeBugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue