Clojuscript, webpack and infering externs on type hints

After working through this tutorial: https://clojurescript.org/guides/webpack

I decided to try something a bit more involved. Interacting with pixi.js. Seems to work fine in normal compilation but falls flat when doing advance compilation.

main.js:2 Uncaught TypeError: Cannot read property '$addChild$' of undefined
    at main.js:2
    at main.js:2
    at main.js:2

I figured it was due to externs not being inferred. I read this guide https://clojurescript.org/guides/externs which says you can infer externs with type hints.

But still get the same error just without the $ signs:

main.js:2 Uncaught TypeError: Cannot read property 'addChild' of undefined
    at main.js:2
    at main.js:2
    at main.js:2

Here’s the code:

(ns minimal-cljs-pixijs.core
  (:require [pixi.js :as px]))

(set! *warn-on-infer* true)

(def app (px/Application. #js {:backgroundColor 0x1099bb}))
(.appendChild (. js/document -body) (. app -view))

(def egg (. px/Sprite from "assets/eggHead.png"))
(.set (.-anchor egg) 0.5)
(set! (.-x egg) (/ (.. app -screen -width) 2))
(set! (.-y egg) (/ (.. app -screen -height) 2))

(.addChild ^js/px.Container (.-stage app) egg)

(defn rotate-egg [delta]
  (set! (.-rotation egg)
        (+ (.-rotation egg)
           (* 0.1 delta))))

(.add (.-ticker app) rotate-egg)

The full project is here: https://github.com/andersmurphy/minimal-cljs-pixijs

Stumped at what’s wrong. Am I doing the type hint correctly? Is this just something that extern inference can’t handle? If so how do you actually go about adding an extern file to a webpack cljs project (can’t seem to find that anywhere in the documentation just seems to assume you have an extern file :thinking:).

Any help greatly appreciated. :grinning:

Try

(def ^js app (px/Application. #js {:backgroundColor 0x1099bb}))

Otherwise app will be treated as a regular CLJS value and no externs will be generated. So everything accessed from app will potentially get renamed. The problem with .addChild is that (.-stage app) is still getting renamed, thus ending up as (.addChild undefined ...). With the above typehint everything accessing app should be safe from renaming.

1 Like

Wow that just worked! That was even simpler than I hoped it would be. Thank you! :partying_face: