Subscribe on changes!

Support Inheritance (extends) in the Composition API

avatar
May 23rd 2023

What problem does this feature solve?

Intro

There is no native process in the Composition API that supports inheritance (extends). This creates a huge blocker for adoption. The Composition API may prefer a composition ideology, but it should allow for inheritance as complementary design element as is simplifies architecture, design, and coding. Composition and Inheritance are complimentary design patterns.

Inheritance and Composition

Inheritance and composition are simply design patterns a user can and should use at will. There is no valid reason that composition abrogates inheritance even in a so-called "composition" API. These two design patterns are not add odds with each other and doesn't necessitate using one over the other. The Options API does not "demand" using inheritance over composition.

While the Composition API "suggests" the composition design, it shouldn't "demand" exclusive use. In fact, there is a huge body of work that use both together. Then, use the Options API? The Composition API provides a valuable, condensed, and simplified coding structure. Why double coding methodologies and mindsets? Mixing the two APIs is problematic and a developer needs to juggle two different mindsets leading to error. Extending one "composable" object from another should be easy.

The primary differences between the Options and Composition API seems to be:

  1. The Options API tends to use a Public first interface...the component is "open" by default.
  2. The Composition API tends to use a Private first interface...the component is "closed" by default.

Project Issues

Forcing Composition API adopters to re-engineer projects to conform to a strict composition ideology is an unnecessary blocker. In fact, the "composition only" ideology is forcing a more verbose method and process when it should be complementary to inheritance. This also leads to the crazy notion of putting most functions in a singular "utility" JS/TS file and "composing" components by importing the needed functions to use in the control functions for the component...little organization, little structure, everything is global, back to the good ol' spaghetti code days. Then, use JS/TS directly and dump the API usage.

What does the proposed API look like?

Class Exposure

In the Composition API, a component is "closed by default"--elements are private by default. Then, expected behavior is that only exposed (i.e., public) elements should be available to the derived component.

Using setup()

<script>
import SomeOtherComponent from some_other_component.vue

export default {
  setup(props, { extends }) {
    ...
    extends({
      SomeOtherComponent
    })
    ...
  }
}
</script>

OR

<script>
import SomeOtherComponent from some_other_component.vue

export default {
  setup(props, { options }) {
    ...
    options({
      extends: SomeOtherComponent,
      ...
    })
    ...
  }
}
</script>

Using <script setup>

<script setup>
import SomeOtherComponent from some_other_component.vue

defineExtends({ SomeOtherComponent })
</script>

OR

<script setup>
import SomeOtherComponent from some_other_component.vue

defineOptions({
  extends: SomeOtherComponent,
...
})
</script>
avatar
May 26th 2023
  • for setup, It should be:
export default {
  extends: Comp,
  setup(){}
}
  • defineOptions already supported extends see
avatar
May 26th 2023

With all due respect, here's exactly what I suggest: if you are using Composition API, then follow the recommended best practice. My opinion is that the concept of "inheritance" is inherently incompatible with the Composition mindset. If you want to reuse logic in Composition API, reuse them as composables. One pattern to rule them of all. I don't see the point of complicating the model with inheritance.

If you believe your suggested API solves a real issue rather than stylistic preferences, please open an RFC discussion here with detailed design, so that it can gather feedback / interest.