The relationship between Kotlin and Java is not the same as TypeScript and JavaScript. TypeScript is intentionally a syntactical superset of JavaScript. It only adds type annotations and nothing else. This allows TypeScript to be easily compatible with JavaScript, with very little risk of future breaks in compatibility.

Kotlin cannot choose the same route as TypeScript, since Java is already statically typed (even if that typing is not always very strong). There is no point in adding type annotations to it. Most of the improvement that Kotlin originally sought (and still seeks) to have on Java are in syntax and semantics. This means Kotlin has to modify the syntax and cannot just be a simple transpiler that naturally incorporates new Java language features.

The interop strategy that Kotlin has chosen instead is:
1. Keep track on what Java is doing.
2. Add compatibility to Java language features when they are released.
3. Avoid introducing incompatible features too quickly when Java is developing the same thing.
4. If the Java development direction is settled but the feature is not released yet, introduce features that have a clear upgrade path for compilation and interop on new Java releases.

Kotlin is already compatible with Java records (just add the @JvmRecord annotation to a data class). This annotation forces the Kotlin data class to be immutable and the compiler will generate a java record for you if you target the JVM.

Nullability marking is not something that is currently being worked on for Java. Some publications have misleadingly modified the title for "JEP 401: Flattened Heap Layouts for Value Objects (Preview)" [1] to "JEP 401: Null-restricted types", because this very early proposal mentions possible interactions with null-restricted types - but the null-restricted proposal doesn't even exist yet. It's quite hard to predict how Kotlin would be compatible with a feature that may or may not come around 2030.

String templates are still a preview feature in Java 21, so don't expect to see them in production before Java 25 in September 2025. String Templates, like string interpolation, is essentially syntactic sugar, but it provide a better story for type-safety and flexibility than classic string interpolation. Kotlin already solves the simple interpolation cases with its string interpolation, but I agree it leaves some things to be desired (multi-line handling is especially painful[2]). The type-safety/flexibility story is generally handled in Kotlin with type-safe builders[3], and it's often a better solution in my opinion, but there many cases where a string template would be more readable.

The main reason Kotlin might need to support string templates, is that all this syntactic sugar has an interface: the StringTemplate interface. Java libraries may rely on it on the far future[3], and then Kotlin will need to maintain compatibility somehow. JetBrains are not ignoring this issue of course. You will find multiple tickets on their tracker talking about custom string interpolation, that even predate the String Templates JEP[5], but it's currently a wait-and-see-approach.

I think the most important set of features for Kotlin to look at is Project Valhalla[6]. It's an even bigger revolution than project Loom. Kotlin is already preparing for this, with value classes[7]. I believe the main reason that value class usage in Kotlin is so highly restricted in Kotlin right now, is that they are waiting for Project Valhalla, and do not want to give up interop later.

You can also think of other past examples when Kotlin did introduced a future earlier than Java, and then gradually made it interoperable. The best example is closures. Kotlin supported closures since its early beta versions (before Java 8 was released), and for a long time supported generating Java 6 bytecode. Since Java 8 closures relied on a new JVM bytecode instruction (InvokeDynamic), Kotlin used a different mechanism to implement closures. When Java 8 was released, they could easily maintain API compatibility with Java, since they are always invoked through an interface. Kotlin eventually added support for generating lambdas in the same style as Java, but they only made this default in Kotlin 1.9[8], to maintain maximum compatibility. This didn't affect interop (which was already resolved since Java 8 was released), it only had impact on bytecode size and perhaps a small performance impact in some cases.

I think this list show that Kotlin is currently handling future interop quite well.

[1] https://openjdk.org/jeps/401

[2] https://youtrack.jetbrains.com/issue/KT-46365/Multiline-stri...

[3] https://kotlinlang.org/docs/type-safe-builders.html

[4] Java is a conservative language and most Java deployments are many versions behind the latest LTS. Until last year (https://newrelic.com/resources/report/2022-state-of-java-eco...), most of the Java systems in production were running Java 8, and only recently Java 11 started becoming the dominant version, with Java 8 strongly trailing behind. Java 21 is coming out this year, but Java 17 is barely deployed anywhere. For this reason, you'll find most libraries target still target Java 8 or Java 11, and avoid Java 17 features like record. Since String Templates will be out only in 2025, I don't expect to see libraries requiring them in production before 2030.

[5] https://youtrack.jetbrains.com/issue/KT-16366

[6] https://openjdk.org/projects/valhalla/

[7] https://youtrack.jetbrains.com/issue/KT-42434/Release-inline...

[8] https://youtrack.jetbrains.com/issue/KT-45375