As was mentioned previously, the landscape of JavaScript development today is filled with third-party frameworks such as React, Node.js, and Vue.js. They enable JavaScript developers to be more efficient and to build better applications and services. This begs the question: Can we use Kotlin in conjunction with popular third-party JavaScript libraries?
Thankfully, the answer is yes. We can leverage our Kotlin code alongside these frameworks in a few different ways:
- Without direct interaction
- By converting TypeScript definitions to work with strongly typed APIs
- Interacting with non-strongly typed APIs directly using dynamic types
The most basic example of mixing Kotlin and JavaScript is writing Kotlin that doesn't rely on any direct interaction with other JavaScript frameworks. This is the approach we've seen so far in this chapter. Our Hello World code didn't know it was going to be run in a JavaScript environment. It didn't work with any framework, manipulate the DOM, or do other domain-specific tasks. This would be the same if we were simply writing our model objects in Kotlin so that they could be reused across multiple Kotlin projects. If we're working with simple data classes, there's a high likelihood they wouldn't need to be dependent on any specific JavaScript APIs.
What happens if we want to use a library that the Kotlin standard library doesn't provide JavaScript bindings for? Examples of this may include jQuery or React. In these cases, we have two options:
- Our first option is to search for any available TypeScript headers for the library and convert them to Kotlin bindings using the conversion tool available at https://github.com/kotlin/ts2kt. The DefinitelyTyped project is a repository of static TypeScript bindings for JavaScript libraries and frameworks. The repository contains definitions for thousands of libraries. If you find definitions for a library you wish to use, you can convert those definitions to Kotlin using the freely available ts2kt tool. When using ts2kt, we can generate a Kotlin file containing strongly typed bindings for whichever library we want to use. We can then reference those definitions from our Kotlin code.
- The second option is to use Kotlin's dynamic types to gain access to JavaScript functions that are available at runtime, but for which we don't have access to static bindings. By defining a variable as dynamic, we can call anything we would like on it, and it will not result in a compiler error. Take the following code snippet, for example:
// results in runtime error if invokeAnything() doesn't exist
val someObject: dynamic = null
someObject.invokeAnything()
This code compiles, but unless the invokeAnything() function is defined somewhere at runtime, this code will result in an exception, as demonstrated in the following screenshot:
By using dynamic types, we have the flexibility to work with any JavaScript we need to, even if we don't have access to static bindings. As mentioned previously, we can find bindings for many popular libraries in the DefinitelyTyped repository that we can then make use of by converting them to Kotlin using ts2kt.
Additionally, JetBrains has provided its own repositories for several popular frameworks. Some of these are listed here:
- Wrappers for popular libraries such as React and Redux—https://github.com/JetBrains/kotlin-wrappers.
- A starter project for building a React app with Kotlin—https://github.com/JetBrains/create-react-kotlin-app.
Between available TypeScript definitions, the JetBrains-provided kotlin-wrappers repository, and dynamic types, Kotlin can potentially harness the full power and functionality of the JavaScript ecosystem.
To illustrate this, in the next section, we're going to generate jQuery bindings for Kotlin and use jQuery to manipulate our web page using Kotlin.