microsoft / microsoft/TypeScript
Abstract property specified on multiple classes loses modifier after intersection
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
🔎 Search Terms
abstract property class intersection InstanceType typeof mixin trait
🕗 Version & Regression Information
- This is the behavior in every version I tried
⏯ Playground Link
💻 Code
abstract class A {
abstract a(): number
}
abstract class A2 {
abstract a(): number
}
abstract class B {
abstract b(): number
}
declare const Base: abstract new () => A & B
// correctly has type error requiring the implementation of 'a' and 'b'
class Foo extends Base {}
declare const FalsePositiveBase: abstract new () => A & A2
// this sould be an error
// if an abstract property appears on multiple classes, it is not treated as abstract
class Bar extends FalsePositiveBase {}
Seems like there must be some flag that associates the abstractness of the original class instance when it is used as a class instance like that, but there is a logic error that checks if the prop exists on other intersection members and erases the modifier, even if all of them are also abstract.
I previously thought this was a workaround:
// can workaround this as follows:
declare const WorkaroundBase: abstract new () => InstanceType<typeof A & typeof A2>
// now gives the correct error that 'a' is missing
class Baz extends WorkaroundBase {}
But realized that it is just treating the constructor as an overload and only using one of the instance types.
🙁 Actual behavior
Behavior for multiple props of the same name was inconsistent with behavior for props with differing names
🙂 Expected behavior
Intersecting multiple props of the same name that all of the abstract modifier should preserve it
Additional information about the issue
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground and reproduce the difference between Foo and Bar using intersections of abstract classes. Trace how the type checker handles the shared abstract member during class extension, then verify that the expected error for Bar is preserved without relying on the workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100