This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-27
Channels
- # announcements (1)
- # aws (8)
- # babashka (77)
- # babashka-sci-dev (8)
- # beginners (29)
- # biff (2)
- # calva (13)
- # cljs-dev (1)
- # clojure (42)
- # clojure-europe (205)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-uk (4)
- # clojurescript (58)
- # conjure (9)
- # data-science (7)
- # datalevin (19)
- # datomic (3)
- # emacs (7)
- # fulcro (15)
- # gratitude (8)
- # lsp (52)
- # meander (3)
- # membrane (92)
- # off-topic (12)
- # re-frame (16)
- # reagent (4)
- # reitit (15)
- # releases (1)
- # sci (30)
- # shadow-cljs (34)
- # tools-deps (5)
- # xtdb (17)
Can ^js
be used in place of ^js/React.Element
? I saw this question come up here (https://github.com/lilactown/helix/pull/104#discussion_r955408172), and I’d like to document this in the cljs api docs so people can just search ^js
and have a canonical description. Please let me know your thoughts!
^js
is the simplified type hint method that has the same effect as the typed variant yes
technically the externs are less precise but that would only be relevant if all code is properly typed
I read the blog post on externs inference that had the full form, and saw that you answered that the full form isn’t needed. I guess this requires understanding why externs can omit the full form? I don’t quite understand.
https://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html
To be sure, ^js
isn’t shadow-specific right?
not actually sure 😛 the cljs default used to warn about ^js
adding extern properties to the generic object. dunno if it still does that
I did some searching here and saw @U2FRKM4TW say that the compiled code is the same for both ^js
and ^js/React.Element
, so the difference must be in the externs file creation unless the compiler throws away the type completely.
shadow-cljs throws it away. the regular compiler uses it. but as I explained in the blog post the closure-compiler doesn't actually use it unless all related code is fully typed
ah I see, so the full form effectively just documents the expected type
Thanks! I’ll write a quick entry and post a link here when done.
@U05224H0W can you say more about the ^clj
and ^goog
tags you mentioned on the blog post?
they aren't actual tags that have any meaning. they just serve to shut up externs inference without generating any externs
shadow-specific?
not really. externs inference just won't warn if the code is hinted. as far as cljs is concerned there is a tag it doesn't know, so doesn't do anything with it
Okay, it looks like I can learn more about this in cljs.analyzer/analyze-dot
here https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L3484-L3546
shadow has its own impl for this if you want to compare https://github.com/thheller/shadow-cljs/blob/bf38b2c4c68c2dbd634948155ca0572cefcf739b/src/main/shadow/build/cljs_hacks.cljc#L476-L544
it looks like (when (not= 'js target-tag) …)
is what causes ^js
to be abbreviated without full class name
this parts adds them https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L3518-L3522
what is the tag meta prefix?
Ah it’s a vector of property names of the full class form with prototype
appended here: https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L970-L978
Okay, I think this is all I need to know right here: https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L3491-L3496
• ^js
adds externs properties on Object
• ^js/React.Element
adds externs properties on React.Element.prototype
correct. although important to know that unless 100% of the code is typed it doesn't matter whether its on object or react.element
right. but wait, I don’t get how that still wouldn’t trigger the warning here for Object
property access: https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L3500-L3503
I think most people are using shadow-cljs these days lol
in regular cljs you have to (set! *warn-on-infer* true)
in your code to actually get any warnings
not a whole lot of people do that I guess, so they don't get any warnings at all for inference
shadow just added the auto part that automatically enables the warnings for your source files
oh my bad, I’m forgetting that the point here is to just write externs and not avoid warnings
btw, I see ^clj
a lot in reagent’s code: https://github.com/reagent-project/reagent/blob/9ddf191a6a7338d226161e8af0d7ecc0bc2a6bae/src/reagent/ratom.cljs#L70
https://github.com/reagent-project/reagent/commit/cec6e437a65f0d3160da040cd0936139e51b5b3b
ha, I thought it was for official cljs too. from the implementation, I can see how it would stop the warnings if they were on
i found at least one usage of it as an inferred tag inside an if-expression: https://github.com/clojure/clojurescript/blob/40358fc4c53090676da82e3f4c52920003678902/src/main/clojure/cljs/analyzer.cljc#L1501-L1504
ah, so shadow-cljs just puts all the inferred externs under ShadowCLJS.prototype
: https://github.com/thheller/shadow-cljs/blob/bf38b2c4c68c2dbd634948155ca0572cefcf739b/src/main/shadow/build/closure.clj#L359-L396
I feel like the table showing where the externs are added is more confusing than helping there
Fyi type hints don't work for dot access in some cases https://clojure.atlassian.net/plugins/servlet/mobile?originPath=%2Fbrowse%2FCLJS-3315#issue/CLJS-3315
thanks. I hadn't noticed that @U050B88UR had commented on that bug, saying it's not a big issue.
It bothers me that someone could correctly follow an official guide like http://cljs.github.io/api/syntax/js-tag and find their code not run. @U061E2UBT if you're able to make edits, could you update the https://cljs.github.io/api/syntax/dot entry to carry a health warning where it talks about foo.bar.baz
style?
@U05224H0W I got rid of the ugly table. I think it works as a bullet list instead
not sure that helps either. I mean you kinda need in depth understanding of what externs are and how they work to understand the difference there?
for example shadow-cljs generates ShadowJS
hints since the function that "provides" JS types is tagged with it. so, the closure compiler will see the returned types as all ShadowJS
. https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/js.js#L25-L28
overall that doesn't matter at all since most other code isn't type hinted, but thats the reason for ShadowJS
and not Object
. when it comes to the end result that would be identical, but there is a thought behind it
oh my
my summary would be that the property is added to externs and as such prevents any renaming of that property name
great, I’ll write that in