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