I'm trying to wrap a JS method like the following:...
# javascript
e
I'm trying to wrap a JS method like the following:
Copy code
parseFromString<MIME extends keyof {
        "text/html": HTMLDocument;
        "image/svg+xml": SVGDocument;
        "text/xml": XMLDocument;
    }>(markupLanguage: string, mimeType: MIME): {
        "text/html": HTMLDocument;
        "image/svg+xml": SVGDocument;
        "text/xml": XMLDocument;
    }[MIME];
Basically it allows:
Copy code
parseFromString(value, "text/html"): HTMLDocument
parseFromString(value, "text/xml"): XMLDocument
parseFromString(value, "image/svg+xml"): SVGDocument
Can I write external declarations in the following form?
Copy code
external class Parser {
  fun parseHtmlFromString(value: String): HTMLDocument
  fun parseXmlFromString(value: String): XMLDocument
  fun parseSvgFromString(value: String): SVGDocument
}
This would make it a lot more usable from Kotlin code.
a
I see, that you could do it in the next way:
Copy code
external class Parser {
  fun parseFromString(markupLanguage: String, mimeType: String): dynamic
}

fun Parser.parseHtmlFromString(markupLanguage: String): HTMLDocument = parseFromString(markupLanguage, "text/html")
fun Parser.parseXmlFromString(markupLanguage: String): XMLDocument = parseFromString(markupLanguage, "text/xml")
fun Parser.parseSvgFromString(markupLanguage: String): SVGDocument = parseFromString(markupLanguage, "image/svg+xml")
e
@Artem Kobzar that's ok for me, thanks! What I would like to avoid tho, is exposing the original external method. Maybe marking the external method as
internal
is enough?
a
Also, you could do it with the original function: https://pl.kotl.in/nqunapjH4
💯 1
e
Oh nice, that's clever. Yeah I can also go with this second solution, probably it's even easier to use for someone coming from JS/TS, as it's a direct mapping
a
Also, there is a black magic solution: https://pl.kotl.in/Ok4ERQlkM
e
This was basically what I was attempting to do (minus the
inline
), but I abandoned it as soon as I got
WRONG_BODY_OF_EXTERNAL_DECLARATION
. It's the easiest approach from a Kotlin developer perspective, but I'm wondering if it's going to not work at all at some point, since we're suppressing it
a
It will not work without inline.
e
Thanks! Do you also see the
WRONG_BODY_OF_EXTERNAL_DECLARATION
error going to be relaxed at some point to accomodate this style? Obviously without suppression you'd get
Wrong body of external declaration. Must be either ' = definedExternally' or { definedExternally }
a
I've just started the discussion about it. @turansky proposed the same thing and we realized that it's really comfortable at some point for inline functions.
✔️ 1
Also, to eliminate
PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR
suppress you could use
asDynamic
on this: https://pl.kotl.in/520m70sny
e
I like this approach of inline functions a lot. As of now the amount of suppressions is pretty high
Copy code
@Suppress("INLINE_EXTERNAL_DECLARATION", "WRONG_BODY_OF_EXTERNAL_DECLARATION", "NOTHING_TO_INLINE", "UnsafeCastFromDynamic")
But I can live with that
I was also just testing out the approach with the sealed interface for
MimeType
, and I'm getting
NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE
.
Should it be suppressed?
Ah forgot
+JsAllowValueClassesInExternals
, my bad
Enabled the language feature, but still getting that
NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE
. Probably it wasn't related. When I remove
@file:JsModule(...)
, the error disappears.
That's why: https://youtrack.jetbrains.com/issue/KT-37776 Workaround is to move the interface to another file. I think I'll keep the
inline
solution tho. Thanks again Artem.