Как установить статическое свойство в классе в Kotlin для Javascript

У меня есть ситуация, когда мне нужно определить статическое свойство в классе в Котлине, и когда он скомпилирован в Javascript, он станет истинным статическим полем этого класса. В этой ситуации объекты-компаньоны не работают.

Например, если у меня есть абстрактный класс и его реализующий класс, как показано ниже:

abstract class MyAbstractClass{ abstract val id: Int } class MyClass: MyAbstractClass(){ override val id: Int = 1 //I want this to actually be "static" on the MyClass } 

Javascript, скомпилированный для этого:

 function MyAbstractClass() { } function MyClass() { MyAbstractClass.call(this); this.id_jz5fma$_0 = 1; } Object.defineProperty(MyClass.prototype, 'id', { get: function () { return this.id_jz5fma$_0; } }); 

Но то, что мне нужно, чтобы скомпилировать это:

 function MyAbstractClass() { } function MyClass() { MyAbstractClass.call(this); } MyClass.id = 1; 

Так что поле id действительно статически существует на MyClass без необходимости создания нового экземпляра MyClass .

Я попытался использовать сопутствующий объект, но создает отдельный объект / функцию MyClass$Companion а затем присваивает ему поле id и никогда не ставит его статически на MyClass .

Как я могу задать установку таких статических полей, как это в Котлин?

Прямо сейчас у нас нет прямого способа сделать это, поэтому я создал проблему https://youtrack.jetbrains.com/issue/KT-18891

В качестве обходного пути вы можете написать такую ​​функцию:

 inline fun <reified T : Any> addStaticMembersTo(source: Any) { val c = T::class.js.asDynamic() val ownNames = js("Object").getOwnPropertyNames(source) as Array<String> val protoNames = js("Object").getOwnPropertyNames(source.asDynamic().constructor.prototype) as Array<String> for (name in ownNames + protoNames) { c[name] = source.asDynamic()[name] } } 

И используйте как:

 class A { companion object { init { addStaticMembersTo<A>(object { val bar = 1 fun foo() {} }) } } } 

или даже сделать доступными членам класса компаньона в качестве статического члена класса:

 class B { companion object { val bar = 1 fun foo() {} // should be at the end of companion object init { addStaticMembersTo<B>(this) } } } 

Полный пример доступен здесь: https://try.kotl.in/#/UserProjects/uube1qikg3vsegtnefo0ad0jag/30f1qf87dt5k5vjhciirt4t108