Spec-Zone.ru › Kotlin 2

Использование кода Kotlin из JavaScript

В зависимости от выбранной системы модулей JavaScript компилятор Kotlin/JS генерирует разные выходные данные. Но в целом компилятор Kotlin генерирует обычные классы, функции и свойства JavaScript, которые можно свободно использовать в коде JavaScript. Однако следует помнить о некоторых нюансах.

Изоляция объявлений в отдельном объекте JavaScript в режиме Plain

Если вы явно задали тип модуля plain, Kotlin создаёт объект, содержащий все объявления Kotlin из текущего модуля. Это сделано для того, чтобы не засорять глобальный объект. Это означает, что для модуля myModule все объявления доступны JavaScript через объект myModule. Например:

fun foo() = "Hello"

Эту функцию можно вызвать из JavaScript следующим образом:

alert(myModule.foo());

Такой прямой вызов функции неприменим, если вы компилируете модуль Kotlin в модули JavaScript, например UMD (настройка по умолчанию для целей browser и nodejs), ESM, CommonJS или AMD. В таких случаях объявления экспортируются в соответствии с выбранной системой модулей JavaScript. Например, при использовании UMD, ESM или CommonJS место вызова будет выглядеть так:

alert(require('myModule').foo());

Дополнительные сведения о системах модулей JavaScript см. в разделе Модули JavaScript.

Структура пакетов

Для большинства систем модулей (CommonJS, Plain и UMD) Kotlin предоставляет JavaScript структуру пакетов. Если вы не определяете объявления в корневом пакете, в JavaScript необходимо использовать полные имена. Например:

package my.qualified.packagename

fun foo() = "Hello"

Например, при использовании UMD или CommonJS место вызова может выглядеть так:

alert(require('myModule').my.qualified.packagename.foo())

При использовании plain в качестве настройки системы модулей место вызова будет выглядеть так:

alert(myModule.my.qualified.packagename.foo());

При компиляции в модули ECMAScript (ESM) информация о пакетах не сохраняется, чтобы уменьшить размер пакета приложения и соответствовать типичной структуре пакетов ESM. В этом случае использование объявлений Kotlin с модулями ES выглядит так:

import { foo } from 'myModule';

alert(foo());

@JsName аннотация

В некоторых случаях (например, для поддержки перегрузок) компилятор Kotlin изменяет имена сгенерированных функций и атрибутов в коде JavaScript. Чтобы управлять сгенерированными именами, можно использовать аннотацию @JsName:

// Module 'kjs'
class Person(val name: String) {
    fun hello() {
        println("Hello $name!")
    }

    @JsName("helloWithGreeting")
    fun hello(greeting: String) {
        println("$greeting $name!")
    }
}

Теперь этот класс можно использовать из JavaScript следующим образом:

// If necessary, import 'kjs' according to chosen module system
var person = new kjs.Person("Dmitry");   // refers to module 'kjs'
person.hello();                          // prints "Hello Dmitry!"
person.helloWithGreeting("Servus");      // prints "Servus Dmitry!"

Если бы мы не указали аннотацию @JsName, имя соответствующей функции содержало бы суффикс, вычисленный на основе сигнатуры функции, например hello_61zpoe$.

Обратите внимание, что в некоторых случаях компилятор Kotlin не изменяет имена:

  • Имена объявлений external не изменяются.

  • Имена всех переопределённых функций в классах, не являющихся external и наследующих классы external, не изменяются.

Параметр @JsName должен быть константной строкой, содержащей допустимый идентификатор. Компилятор сообщит об ошибке при любой попытке передать в @JsName строку, не являющуюся идентификатором. Следующий пример приведёт к ошибке компиляции:

@JsName("new C()")   // error here
external fun newC()

@JsExport аннотация

Применив аннотацию @JsExport к объявлению верхнего уровня (например, классу, интерфейсу или функции), можно сделать объявления Kotlin доступными из JavaScript или TypeScript. Аннотация экспортирует все вложенные объявления под именами, заданными в Kotlin.

Вот пример экспорта интерфейса Kotlin с вложенным классом и именованным сопутствующим объектом:

@JsExport
interface Identity {
     class Metadata(val tag: String)

    companion object Registry {
        val defaultTag = "GUEST"
    }
}

В настоящее время аннотация @JsExport — единственный способ сделать ваши функции видимыми из Kotlin.

Аннотация @JsExport также доступна:

  • В общем коде многоплатформенных проектов. Она действует только при компиляции для целевой платформы JavaScript и позволяет также экспортировать объявления Kotlin, не относящиеся к конкретной платформе.

  • Вместе с аннотацией @JsName для задания имён сгенерированных и экспортируемых функций. Это помогает устранить неоднозначность при экспорте (например, перегрузок функций с одинаковыми именами).

  • На уровне файла с помощью @file:JsExport.

Экспорт классов-значений

Классы встраиваемых значений Kotlin можно экспортировать как обычные классы TypeScript.

Чтобы экспортировать класс-значение, пометьте его аннотацией @JsExport в Kotlin:

// Kotlin
@JsExport
@JvmInline
value class Email(val address: String) {
    init { require(address.contains("@")) { "Invalid email" } }
}

@JsExport
class AuthService {
    suspend fun login(email: Email): String = ...
}

В TypeScript он выглядит как обычный класс:

// TypeScript
import { AuthService, Email } from "..."
const auth = new AuthService();

console.log(await auth.login(new Email("jane@example.com"))); 
// "Welcome, jane@example.com!"
console.log(await auth.login(new Email("not-an-email"))); 
// "Invalid email"

Экспорт приостанавливающих лямбда-выражений

Приостанавливающие лямбда-выражения Kotlin можно экспортировать как JavaScript асинхронные функции:

  1. Чтобы включить эту функцию, добавьте следующий параметр компилятора в файл build.gradle.kts:

    kotlin {
        js {
            compilations.all {
                compileTaskProvider.configure {
                    compilerOptions {
                        freeCompilerArgs.add("-Xsuspend-lambda-exporting")
                    }
                }
            }
        }
    }
    
  2. Пометьте соответствующие объявления Kotlin аннотацией @JsExport:

    // Kotlin
    @JsExport
    class TaskRunner {
        suspend fun runTask(task: suspend () -> String): String {
            return task()
        }
    }
    
  3. В TypeScript лямбда-выражение suspend будет преобразовано в обычную функцию async:

    // TypeScript
    import { TaskRunner } from "..."
    
    const runner = new TaskRunner();
    const result = await runner.runTask(async () => "done");
    console.log(result); // "done"
    

@JsNoRuntime аннотация

Интерфейсы Kotlin можно экспортировать в JavaScript/TypeScript с помощью аннотации @JsNoRuntime. Она позволяет напрямую преобразовывать их в обычные интерфейсы TypeScript.

Например, чтобы экспортировать интерфейс Kotlin из многоплатформенного проекта Kotlin:

  1. Пометьте интерфейс Kotlin аннотацией @JsNoRuntime в общем коде:

    // commonMain
    import kotlin.js.JsNoRuntime
    
    @JsNoRuntime
    expect interface DataProcessor {
        fun process(data: String): Int 
    }
    
  2. Предоставьте фактическую реализацию с помощью @JsNoRuntime в исходном коде для JS:

    // jsMain
    import kotlin.js.JsNoRuntime
    
    @JsNoRuntime
    actual interface DataProcessor {
        actual fun process(data: String): Int
    } 
    
  3. В TypeScript интерфейс будет преобразован в обычный интерфейс TypeScript:

    // Generated .d.ts
    export interface DataProcessor {
        process(data: string): number;
    }
    

Для многоплатформенных проектов Kotlin действуют следующие общие правила:

  • Объявления интерфейсов expect и actual должны быть помечены аннотацией @JsNoRuntime. Исключение составляют реализации external в платформенном коде на стороне actual, которые не требуют аннотации.

  • Использовать объявления интерфейсов external в общем коде на стороне expect запрещено. Вместо этого используйте обычные интерфейсы, помеченные аннотацией @JsNoRuntime.

Экспорт интерфейсов Kotlin с помощью @JsNoRuntime имеет некоторые ограничения. Аннотацию нельзя использовать с:

  • Интерфейсами external, поскольку по умолчанию они уже ведут себя так, как если бы у них была аннотация @JsNoRuntime. Её добавление приводит к предупреждению компилятора.

  • Проверками типов is и as.

  • Ссылками на классы с использованием синтаксиса ::class.

  • Интерфейсами, передаваемыми как аргумент реифицированного типа.

@JsStatic

Аннотация @JsStatic указывает компилятору сгенерировать дополнительные статические методы для целевого объявления. Это позволяет напрямую использовать статические члены из кода Kotlin в JavaScript.

Аннотацию @JsStatic можно применять к функциям, определённым в именованных объектах, а также в сопутствующих объектах, объявленных внутри классов и интерфейсов. При использовании этой аннотации компилятор сгенерирует как статический метод объекта, так и метод экземпляра в самом объекте. Например:

// Kotlin
class C {
    companion object {
        @JsStatic
        fun callStatic() {}
        fun callNonStatic() {}
    }
}

Теперь функция callStatic() является статической в JavaScript, а функция callNonStatic() — нет:

// JavaScript
C.callStatic();              // Works, accessing the static function
C.callNonStatic();           // Error, not a static function in the generated JavaScript
C.Companion.callStatic();    // Instance method remains
C.Companion.callNonStatic(); // The only way it works

Аннотацию @JsStatic также можно применить к свойству объекта или сопутствующего объекта. В этом случае его методы получения и установки становятся статическими членами этого объекта или класса, содержащего сопутствующий объект.

Эта функция находится на стадии экспериментальной разработки. Оставляйте отзывы в нашем трекере задач YouTrack.

Использование типа BigInt для представления типа Long в Kotlin

При компиляции в современный JavaScript (ES2020) Kotlin/JS использует встроенный тип BigInt JavaScript для представления значений Long Kotlin.

Чтобы включить поддержку типа BigInt, добавьте следующий параметр компилятора в файл build.gradle(.kts):

// build.gradle.kts
kotlin {
    js {
        ...
        compilerOptions {
            freeCompilerArgs.add("-Xes-long-as-bigint")
        }
    }
}

Эта функция находится на стадии экспериментальной разработки. Оставляйте отзывы в нашем трекере задач YouTrack.

Использование Long в экспортируемых объявлениях

Поскольку тип Long в Kotlin может компилироваться в тип BigInt в JavaScript, Kotlin/JS поддерживает экспорт значений Long в JavaScript.

Чтобы включить эту функцию:

  1. Разрешите экспорт Long в Kotlin/JS. Добавьте следующий параметр компилятора в атрибут freeCompilerArgs файла build.gradle(.kts):

    // build.gradle.kts
    kotlin {
       js {
           ...
           compilerOptions { 
               freeCompilerArgs.add("-XXLanguage:+JsAllowLongInExportedDeclarations")
           }
       }
    }
    
  2. Включите тип BigInt. Инструкции см. в разделе Использование типа BigInt для представления типа Long в Kotlin.

Использование типа BigInt64Array для представления типа LongArray в Kotlin

При компиляции в JavaScript Kotlin/JS может использовать встроенный тип BigInt64Array JavaScript для представления значений LongArray в Kotlin.

Чтобы включить поддержку типа BigInt64Array, добавьте следующий параметр компилятора в файл build.gradle(.kts):

// build.gradle.kts
kotlin {
    js {
        ...
        compilerOptions {
            freeCompilerArgs.add("-Xes-long-as-bigint")
        }
    }
}

Эта функция находится на стадии экспериментальной разработки. Оставляйте отзывы в нашем трекере задач YouTrack.

Типы Kotlin в JavaScript

Посмотрите, как типы Kotlin преобразуются в типы JavaScript:

Kotlin

JavaScript

Комментарии

Byte, Short, Int, Float, Double

Number

Char

Number

Число представляет собой код символа.

Long

BigInt

Необходимо настроить параметр компилятора -Xes-long-as-bigint.

Boolean

Boolean

String

String

Array

Array

ByteArray

Int8Array

ShortArray

Int16Array

IntArray

Int32Array

CharArray

UInt16Array

Имеет свойство $type$ == "CharArray".

FloatArray

Float32Array

DoubleArray

Float64Array

LongArray

BigInt64Array

BooleanArray

Int8Array

Имеет свойство $type$ == "BooleanArray".

List, MutableList

KtList, KtMutableList

Предоставляет Array через KtList.asJsReadonlyArrayView или KtMutableList.asJsArrayView.

Map, MutableMap

KtMap, KtMutableMap

Предоставляет Map ES2015 через KtMap.asJsReadonlyMapView или KtMutableMap.asJsMapView.

Set, MutableSet

KtSet, KtMutableSet

Предоставляет Set ES2015 через KtSet.asJsReadonlySetView или KtMutableSet.asJsSetView.

Unit

Undefined

Можно экспортировать в качестве возвращаемого типа, но не в качестве типа параметра.

Any

Object

Throwable

Error

enum class Type

Type

Элементы перечисления доступны как статические свойства класса (Type.ENTRY).

Nullable Type?

Type | null | undefined

Все остальные типы Kotlin, кроме отмеченных @JsExport

Не поддерживается

Включает беззнаковые целочисленные типы Kotlin.

Кроме того, важно знать следующее:

  • Kotlin сохраняет семантику переполнения для kotlin.Int, kotlin.Byte, kotlin.Short, kotlin.Char и kotlin.Long.

  • Kotlin не может различать числовые типы во время выполнения (за исключением kotlin.Long), поэтому следующий код работает:

    fun f() {
        val x: Int = 23
        val y: Any = x
        println(y as Float)
    }
    
  • Kotlin сохраняет отложенную инициализацию объектов в JavaScript.

26 августа 2026 г.
Использование зависимостей из npmМодули JavaScript

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/js-to-kotlin-interop.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API