TypeScript: TS demands that abstract properties with type never are implemented

Bug Report

🔎 Search Terms

abstract property inheritance never

🕗 Version & Regression Information

Current nightly v5.2.0-dev.20230720

⏯ Playground Link

Playground

💻 Code

abstract class P {
  abstract foo: never
}

class C extends P {} // error C does not implement foo

class D extends P {
  foo: never // Property 'foo' has no initializer and is not definitely assigned in the constructor.
}

🙁 Actual behavior

Error in class C, TS demands foo to be implemented.

🙂 Expected behavior

class C should not produce an error. Absence of foo matches the type constraint in P.

Comments

I suppose this is a bug - certainly I did not expect TS to ask me to implement a property with type never. A function with a type never argument would not let me pass it, and I expected abstract properties to be similar.

function f(a: never) {}
f(true) // error

“Fixing” this provides the benefit of being able to create optional abstract properties, e.g.

abstract class P {
  abstract foo: boolean | never
}

class C extends P {} // TS should allow this child class, because of the never option.

Relates to #40635 (Optional abstract properties)

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (5 by maintainers)

Most upvoted comments

The first point is a direct consequence of the second: the type can’t be satisfied, it’s an empty set, so any operation that “produces” a value of type never cannot ever complete normally according to the type system and must throw an exception. To do otherwise would be a type violation.

To be clear: the only reason absent properties can’t be typed never is because they evaluate to undefined (a unit type) at runtime. If it was a runtime error to access them instead, then this typing would make sense.

#47071 (comment)

Record<string, never> describes a type that, if you accessed any of its properties, you’d get an exception.

Ergo properties that are typed never explicit mean “will throw upon access”, not “does never exist”.

TypeScript does not have a way to describe a type that never has a specific property. For this you would require the “Exact Types” feature: #12936

Right, so it’s a language issue