| Concept | Java | Kotlin | TypeScript |
|---|---|---|---|
| Variable Declaration | int age = 25; |
val age: Int = 25 |
let age: number = 25 |
| Immutable Variable | final int age = 25; |
val age: Int = 25 |
const age: number = 25 |
| Type inference | var age = 25; (only for local variables) |
val age = 25 (anywhere, also for return types) |
let age = 25 (anywhere, also for return types) |
| Nullable declaration | N/A (nulls allowed everywhere) | name: String? |
name?: string (undefined) |
| Nullable dereferencing | Optional.ofNullable(person).map(p -> p.name).orElse(null) (even more difficult with nested nullability) |
person?.name |
person?.name |
| Nullable fallback | if (person.name != null) person.name; else ""; |
person.name ?: "" |
person.name ?? '' |
| Function Declaration | int add(int a, int b) { return a + b; } (only inside of classes) |
fun add(a: Int, b: Int) = a + b |
function add(a: number, b: number) { return a + b } |
| Class Declaration | class Person {} |
class Person |
class Person {} |
| Data Class | record Person(String name, int age) {} (no copy constructors) |
data class Person(val name: String, val age: Int) with copy() methods |
{name: string, age: number}, can be copied with {...object, age: 21} |
| Constructor Parameters | public class Service { Dependency dependency; public Service(Dependency dependency) { this.dependency = dependency; } } |
class Service(val dependency: Dependency) |
class Service { constructor(public dependency: Dependency) {} } |
| Class reference | Person.class |
Person::class |
Person |
| Member reference | Person.class.getDeclaredField("name") |
Person::name (type-safe reflection) |
Person.prototype.name |
| Inheritance | class Student extends Person {} |
class Student: Person() |
class Student extends Person {} |
| Interface Implementation | class Dog implements Animal {} |
class Dog: Animal |
class Dog implements Animal {} |
| Object Creation | Person person = new Person("John", 25); |
val person = Person("John", 25) |
let person = new Person("John", 25) |
| String Interpolation | String message = "Hello " + name; |
val message = "Hello $name" |
let message = `Hello ${name} |
| Default Parameters | N/A | fun greet(name: String = "Guest") |
function greet(name: string = "Guest") |
| Extension functions | N/A, usually static utility methods with parameters | fun LocalDate.today() = ... |
interface Date { function today() {...} } |
| Lambda Expressions | Runnable r = () -> System.out.println("Hi"); |
val greet = { println("Hi") } |
const greet = () => { console.log('Hi') } |
| Access Modifiers | public, protected, private, package-private by default |
public (default), protected, private, internal |
public (default), protected, private |
| Generics | List<String> list = new ArrayList<>(); |
val list = ArrayList<String>() |
let list: Array<string> = [] |
| List creation | List.of(1, 2, 3); |
listOf(1, 2, 3) |
[1, 2, 3] |
| Map creation | Map.of("key1", 1, "key2", 2); (null values not allowed) |
mapOf("key1" to 1, "key2" to 2) |
{key1: 1, key2: 2} |
| Value transformation | list.stream().map(i -> i * 2).collect(toList()); |
list.map { it * 2 } |
list.map(i => i * 2) |
| Semicolons | Required | Optional | Optional |
| Readable test names | @Test void myCoolMethodDoesThisAndThat() {} |
@Test fun my cool method does this and that() {} |
test('my cool method does this and that') |
| Asynchronous Code | CompletableFuture.supplyAsync(() -> ...) (no syntactic support) |
suspend functions built-in |
async function fetchData() { ... } async/await built-in |
See TSGenerator in klite-json for generating TypeScript interfaces from Kotlin data classes.