'Clojurscript: extend a Javascript class

I'm trying to use a particular JavaScript framework which requires extending a base class to use it for application.

Basically I want to do the following as idiomatic ClojureScript.

class Foo extends Bar {
  constructor() { super("data") }
  method1(args) { /* do stuff */ }
}

I tried

(defn foo
  []
  (reify
    js/Bar
    (constructor [this] (super this "data"))
    (method1 [this args] )))

Which would work if I'd create a new class from Object, but as shadow-cljs correctly complains, "Symbol js/Bar is not a protocol". Also, I don't want to add methods but create a subclass that inherits somemethods and overloads others.

I thought about using proxy, but "core/proxy is not defined".

Of course I could create an instance of Bar and set! new methods, but that feels like giving up and using an inferior language.



Solution 1:[1]

CLJS (still) has no built-in support for class ... extends ....

However in recent shadow-cljs versions I added support for class as well as extends. This will emit a standard JS class and does not require any hacky workarounds to get it working.

Translating this example

class Foo extends Bar {
  constructor() { super("data") }
  method1(args) { /* do stuff */ }
}

would be

(ns your.app
  (:require [shadow.cljs.modern :refer (defclass)]))

(defclass Foo
  ;; extends takes a symbol argument, referencing the super class
  ;; could be a local symbol such as Bar
  ;; a namespaced symbol such as alias/Bar
  ;; or just a global via js/Bar
  (extends Bar)

  (constructor [this]
    (super "data"))

  ;; adds regular method, protocols similar to deftype/defrecord also supported
  Object
  (method1 [this args]
    ;; do stuff
    ))

More complex examples of defclass can be found here and here.

Currently this only ships with shadow-cljs but technically you can take the modern.cljc and modern.cljs files from here and put them into your project. It should work with all build tools then.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Thomas Heller