Can someone tell why `Promise<List<Item>>` is expo...
# javascript
v
Can someone tell why
Promise<List<Item>>
is exported to TypeScript as
Promise<any>
while
Promise<JsArray<Item>>
preserves both the container and item types? Is it expected behavior and we should use `JsArray`/`JsReadonlyArray` to preserve list item type in the Typescript declarations?
Copy code
// JsItemsRepository.kt file

@OptIn(ExperimentalJsCollectionsApi::class)
class JsItemsRepository() {
    fun getAllArrayAsync(): Promise<JsReadonlyArray<Item>> = scope.promise { … }
    fun getAllListAsync(): Promise<List<Item>> = scope.promise { … }
    fun getFirstAsync(): Promise<Item> = scope.promise { … }
}

// mymodule.d.ts file

class JsItemsRepository {
    getAllArrayAsync(): Promise<ReadonlyArray<com.test.my.Item>>;
    getAllListAsync(): Promise<any/* kotlin.collections.KtList<com.test.my.Item> */>;
    getFirstAsync(): Promise<com.test.my.Item>;
}
e
Hey! Which version of Kotlin are you using?
v
Hey! The latest and greatest: 2.1.21
FWIW my Gradle
js
block is:
Copy code
kotlin {
    js {
        browser { }
        binaries.executable()
        generateTypeScriptDefinitions()
    }
}
e
This looks like the compiler not detecting that the Collection type
List
must be exported. To prove it, add an exported dummy function that returns
List<Item>
, and you'll see the
Promise
type will be correctly generated. @Artem Kobzar let me know if you know of an open issue for this one, or if I have to create one.
😲 1
v
Magic!
Copy code
class JsItemRepository {
    getItems(): kotlin.collections.KtList<com.test.my.Item>;
    getAllAsync(): Promise<ReadonlyArray<com.test.my.Item>>;
    getAllListAsync(): Promise<kotlin.collections.KtList<com.test.my.Item>>;
    getFirstAsync(): Promise<com.test.my.Item>;
}
Thanks @Edoardo Luppi
e
Obviously that workaround is sub-optimal, but at least you know how it works now!
👍 1
a
Oh, there is no known issue like this. Volodymyr, could you please create an issue in YouTrack?
👍 1
v
Sure thing! Do you need a repro project, or the example I provided here is enough?
a
I believe you can just provide in the description a simple top-level function with a
Promise<List<Int>>
return and the text of the generated d.ts for the function. So, it would be like this:
Copy code
fun foo(): Promise<List<Int>> = ...
The generated d.ts:
Copy code
declare function foo(): Promise<any/* kotlin.collections.KtList<number> */>>
However the expected behavior is:
Copy code
declare function foo(): Promise<kotlin.collections.KtList<number>>>
👍 1
e
A very basic reproducer is:
Copy code
// main.kt

// List won't be exported to KtList
@JsExport
fun promiseListExport(): Promise<List<Int>> {
    return Promise.resolve(listOf(1))
}

// Uncomment the following function so that the compiler
// picks up the List type and correctly exports it
// @JsExport
// fun listExport(): List<Int> {
//     return listOf(1)
// }
thank you color 1
v