-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Closed
Copy link
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-repros
Milestone
Description
Bug Report
🔎 Search Terms
type narrowing assertNever never unreachable
🕗 Version & Regression Information
- This changed between versions 4.7.4 and 4.8.x
⏯ Playground Link
Playground Link: Provided
💻 Code
enum PropertyType {
String = 'string',
Number = 'number',
Unknown = 'unknown',
}
interface Property<Type extends PropertyType, Value extends unknown = unknown> {
type: Type;
value: Value;
}
type StringProperty = Property<PropertyType.String, string>;
type NumberProperty = Property<PropertyType.Number, number>;
type UnknownProperty = Property<PropertyType.Unknown, unknown>;
type PropertyObject =
| StringProperty
| NumberProperty
| UnknownProperty
type PropertyObjectOrEmpty = PropertyObject | { type: PropertyType; value: undefined };
interface Edit<VT extends PropertyObject = PropertyObject> {
type: 'edit';
property: VT;
}
interface Add<VT extends PropertyObjectOrEmpty = PropertyObjectOrEmpty> {
type: 'add';
property: VT;
}
function assertNever(n: never): never {
throw new Error('nope');
}
function doStuff(action: Edit | Add) {
if (action.property.value == null) {
// do something
} else if (action.property.type === PropertyType.Unknown) {
// do something else
} else {
// this line is reachable, but compiles without error!
assertNever(action.property);
}
}
doStuff({
type: 'edit',
property: {
type: PropertyType.String,
value: 'hello, world'
}
})
Output
"use strict";
var PropertyType;
(function (PropertyType) {
PropertyType["String"] = "string";
PropertyType["Number"] = "number";
PropertyType["Unknown"] = "unknown";
})(PropertyType || (PropertyType = {}));
function assertNever(n) {
throw new Error('nope');
}
function doStuff(action) {
if (action.property.value == null) {
// do something
}
else if (action.property.type === PropertyType.Unknown) {
// do something else
}
else {
// this line is reachable, but compiles without error!
assertNever(action.property);
}
}
doStuff({
type: 'edit',
property: {
type: PropertyType.String,
value: 'hello, world'
}
});
Compiler Options
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2017",
"jsx": "react",
"module": "ESNext",
"moduleResolution": "node"
}
}
🙁 Actual behavior
Code compiles without error, but assertNever
is hit at runtime.
🙂 Expected behavior
Compilation error: the type of action.property
at the point it's passed to assertNever
is not never
. (4.7 does this.)
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-repros