🚀 Kotlin vs Dart / TypeScript 语法对照手册
🎯 目标读者:有 Android/Kotlin 基础,想快速上手 Flutter(Dart) 或 前端(TypeScript) 的开发者
📖 阅读建议:每节先看 Kotlin,再对照 Dart / TS,找"感觉相似"的地方,学习效率翻倍!
目录
- 变量与常量
- 基本数据类型
- 字符串模板
- 函数定义
- 可空类型与空安全
- 条件判断
- 循环
- 集合:List / Map / Set
- 类与构造函数
- 继承与接口
- 数据类
- Lambda 与高阶函数
- 扩展函数/方法
- 异步编程
- 枚举
- 类型判断与转换
- 解构赋值
- 模块与导入
1. 变量与常量
💡 核心口诀:
var= 可变,val/const/final= 不可变
┌─────────────┬──────────────────────────────┬─────────────────────────────────┐
│ 场景 │ Kotlin │ Dart / TypeScript │
├─────────────┼──────────────────────────────┼─────────────────────────────────┤
│ 可变变量 │ var name = "张三" │ Dart: var name = "张三"; │
│ │ │ TS: let name = "张三"; │
├─────────────┼──────────────────────────────┼─────────────────────────────────┤
│ 不可变变量 │ val age = 18 │ Dart: final age = 18; │
│ │ │ TS: const age = 18; │
├─────────────┼──────────────────────────────┼─────────────────────────────────┤
│ 编译期常量 │ const val PI = 3.14 │ Dart: const pi = 3.14; │
│ │ │ TS: (无区别,同 const) │
└─────────────┴──────────────────────────────┴─────────────────────────────────┘
📝 代码示例
Kotlin
var score = 100 // 可变
val maxScore = 1000 // 不可变(运行时赋值)
const val TAG = "MyApp" // 编译期常量
Dart
var score = 100; // 可变
final maxScore = 1000; // 不可变(运行时赋值)
const tag = "MyApp"; // 编译期常量
TypeScript
let score = 100; // 可变
const maxScore = 1000; // 不可变
// TS 没有编译期常量的区分,统一用 const
2. 基本数据类型
💡 关键差异:Kotlin 中一切皆对象;Dart 无
int/double之外的整型;TS 只有number
| 类型 | Kotlin | Dart | TypeScript |
|---|---|---|---|
| 整数 | Int, Long | int | number |
| 浮点数 | Float, Double | double | number |
| 布尔 | Boolean | bool | boolean |
| 字符串 | String | String | string |
| 字符 | Char | ❌(无单独字符类型) | string(长度1) |
| 任意类型 | Any | dynamic / Object | any / unknown |
| 空类型 | Nothing | Null | null / undefined |
📝 代码示例
Kotlin
val i: Int = 42
val d: Double = 3.14
val b: Boolean = true
val s: String = "Hello"
val c: Char = 'A'
val x: Any = "什么都行"
Dart
int i = 42;
double d = 3.14;
bool b = true;
String s = "Hello";
dynamic x = "什么都行"; // 运行时类型
Object y = "也行"; // 编译期Object
TypeScript
let i: number = 42;
let d: number = 3.14; // 整数和浮点都是 number
let b: boolean = true;
let s: string = "Hello";
let x: any = "什么都行";
let y: unknown = "更安全的any";
3. 字符串模板
💡 三者几乎一样! 都支持
$变量和${表达式},Kotlin 多了三引号多行字符串
Kotlin
val name = "世界"
val age = 18
println("你好,$name!") // 简单变量
println("明年你 ${age + 1} 岁了") // 表达式
val multiLine = """
第一行
第二行
""".trimIndent() // 多行字符串
Dart
var name = "世界";
var age = 18;
print("你好,$name!"); // 简单变量
print("明年你 ${age + 1} 岁了"); // 表达式
var multiLine = """
第一行
第二行
"""; // 多行字符串
TypeScript
const name = "世界";
const age = 18;
console.log(`你好,${name}!`); // 注意:TS 用反引号 ``
console.log(`明年你 ${age + 1} 岁了`);
const multiLine = `
第一行
第二行
`; // 多行字符串(反引号即可)
⚠️ 注意:TypeScript 必须用反引号
`才能插值,单/双引号不行!
4. 函数定义
💡 类型位置不同:Kotlin/Dart 类型在前,TS 类型在后(冒号标注)
Kotlin
// 标准函数
fun add(a: Int, b: Int): Int {
return a + b
}
// 单行简写(表达式函数体)
fun add(a: Int, b: Int) = a + b
// 默认参数
fun greet(name: String = "朋友") = "你好,$name"
// 命名参数调用
greet(name = "小明")
Dart
// 标准函数
int add(int a, int b) {
return a + b;
}
// 箭头函数(单行)
int add(int a, int b) => a + b;
// 默认参数(命名参数用 {} 包裹)
String greet({String name = "朋友"}) => "你好,$name";
// 命名参数调用
greet(name: "小明");
TypeScript
// 标准函数
function add(a: number, b: number): number {
return a + b;
}
// 箭头函数
const add = (a: number, b: number): number => a + b;
// 默认参数
function greet(name: string = "朋友"): string {
return `你好,${name}`;
}
// 可选参数(加 ?)
function log(msg: string, level?: string) { ... }
5. 可空类型与空安全
💡 这是三者差异最大的地方,也是现代语言最重要的特性之一!
Kotlin: 类型后加 ? String? = 可空
Dart: 类型后加 ? String? = 可空(Dart 2.12+ 空安全)
TS: 类型后加 | null string | null = 可空
空安全操作符对比
| 操作 | Kotlin | Dart | TypeScript |
|---|---|---|---|
| 声明可空 | String? | String? | string | null |
| 安全调用 | obj?.method() | obj?.method() | obj?.method() |
| Elvis(默认值) | val ?? "默认" ❌ 用 ?: | val ?? "默认" | val ?? "默认" |
| 非空断言 | val!! | val! | val! |
| 空值合并赋值 | a ?: b(Elvis) | a ?? b | a ?? b |
📝 代码示例
Kotlin
var name: String? = null // 可空
val len = name?.length // 安全调用,结果 Int?
val result = name ?: "默认" // Elvis 操作符
val force = name!!.length // 非空断言(为空时崩溃!慎用)
// let 配合 ?: 使用
name?.let { println("名字是 $it") }
Dart
String? name = null; // 可空
int? len = name?.length; // 安全调用
String result = name ?? "默认"; // 空值合并
String force = name!; // 非空断言(为空时崩溃!慎用)
// 空感知赋值
name ??= "默认名字"; // 只有 name 为 null 时才赋值
TypeScript
let name: string | null = null; // 可空
const len = name?.length; // 可选链
const result = name ?? "默认"; // 空值合并
const force = name!; // 非空断言(TS编译器断言,不是运行时)
// 类型守卫
if (name !== null) {
console.log(name.length); // 这里 name 是 string 类型
}
6. 条件判断
Kotlin
// if-else(可作表达式!)
val max = if (a > b) a else b
// when(强化版 switch)
when (score) {
100 -> println("满分!")
in 90..99 -> println("优秀")
in 60..89 -> println("良好")
else -> println("不及格")
}
// when 作表达式
val grade = when {
score >= 90 -> "A"
score >= 60 -> "B"
else -> "C"
}
Dart
// if-else(不能作表达式)
int max = a > b ? a : b; // 三目运算符
// switch
switch (score) {
case 100:
print("满分!");
break;
default:
print("普通分");
}
// Dart 3.0+ 支持 switch 表达式 🎉
var grade = switch (score) {
>= 90 => "A",
>= 60 => "B",
_ => "C"
};
TypeScript
// if-else
const max = a > b ? a : b; // 三目运算符
// switch
switch (score) {
case 100:
console.log("满分!");
break;
default:
console.log("普通分");
}
// 无 when,用对象映射模拟
const gradeMap: Record<string, string> = {
A: "优秀", B: "良好", C: "一般"
};
7. 循环
Kotlin
// for 区间循环
for (i in 1..5) print(i) // 1 2 3 4 5
for (i in 1 until 5) print(i) // 1 2 3 4(不含5)
for (i in 5 downTo 1) print(i) // 5 4 3 2 1
for (i in 1..10 step 2) print(i) // 1 3 5 7 9
// 遍历集合
val list = listOf("A", "B", "C")
for (item in list) println(item)
list.forEachIndexed { index, value -> println("$index: $value") }
// while
var i = 0
while (i < 5) { println(i); i++ }
Dart
// for 循环
for (int i = 1; i <= 5; i++) print(i);
// for-in 遍历集合
var list = ["A", "B", "C"];
for (var item in list) print(item);
// forEach
list.forEach((item) => print(item));
list.asMap().forEach((index, value) => print("$index: $value"));
// while
int i = 0;
while (i < 5) { print(i); i++; }
TypeScript
// for 循环
for (let i = 1; i <= 5; i++) console.log(i);
// for-of 遍历(推荐)
const list = ["A", "B", "C"];
for (const item of list) console.log(item);
// forEach
list.forEach((item, index) => console.log(`${index}: ${item}`));
// for-in 遍历对象的 key(不建议用于数组!)
const obj = { a: 1, b: 2 };
for (const key in obj) console.log(key);
8. 集合:List / Map / Set
💡 Kotlin 区分 可变/不可变集合;Dart 和 TS 默认可变
Kotlin
// List
val immutableList = listOf(1, 2, 3) // 不可变
val mutableList = mutableListOf(1, 2, 3) // 可变
mutableList.add(4)
// Map
val map = mapOf("name" to "张三", "age" to 18)
val mutableMap = mutableMapOf("name" to "张三")
mutableMap["city"] = "北京"
// Set
val set = setOf(1, 2, 3, 2) // {1, 2, 3} 自动去重
Dart
// List
var list = [1, 2, 3];
list.add(4);
var fixed = List.unmodifiable([1, 2, 3]); // 不可变
// Map
var map = {"name": "张三", "age": 18};
map["city"] = "北京";
// Set
var set = {1, 2, 3, 2}; // {1, 2, 3} 自动去重
Set<int> emptySet = {}; // 注意:{} 默认是 Map,需要指定类型
TypeScript
// Array(List)
const list: number[] = [1, 2, 3];
list.push(4);
const readonlyList: readonly number[] = [1, 2, 3]; // 只读
// Map(对象 or Map类)
const obj: Record<string, any> = { name: "张三", age: 18 };
const map = new Map<string, any>();
map.set("name", "张三");
// Set
const set = new Set([1, 2, 3, 2]); // {1, 2, 3}
集合常用操作对比
| 操作 | Kotlin | Dart | TypeScript |
|---|---|---|---|
| 过滤 | .filter { it > 2 } | .where((e) => e > 2) | .filter(e => e > 2) |
| 映射 | .map { it * 2 } | .map((e) => e * 2) | .map(e => e * 2) |
| 求和 | .sum() | .reduce((a,b) => a+b) | .reduce((a,b) => a+b) |
| 查找 | .find { it > 2 } | .firstWhere((e)=>e>2) | .find(e => e > 2) |
| 是否存在 | .any { it > 2 } | .any((e) => e > 2) | .some(e => e > 2) |
| 全部满足 | .all { it > 0 } | .every((e) => e > 0) | .every(e => e > 0) |
9. 类与构造函数
Kotlin
class Person(
val name: String, // 主构造函数 + 属性
var age: Int
) {
init {
println("创建了 $name") // 初始化块
}
// 次构造函数
constructor(name: String) : this(name, 0)
fun introduce() = "我是$name,$age 岁"
}
val p = Person("张三", 18)
Dart
class Person {
final String name;
int age;
// 构造函数(简写,自动赋值)
Person(this.name, this.age);
// 命名构造函数
Person.anonymous() : name = "匿名", age = 0;
String introduce() => "我是$name,$age 岁";
}
var p = Person("张三", 18);
var q = Person.anonymous();
TypeScript
class Person {
// 方式1:属性声明 + constructor
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 方式2:构造函数参数简写(推荐)
// constructor(public name: string, public age: number) {}
introduce(): string {
return `我是${this.name},${this.age} 岁`;
}
}
const p = new Person("张三", 18);
10. 继承与接口
Kotlin
// 接口
interface Flyable {
fun fly()
fun land() = println("降落") // 默认实现
}
// 抽象类
abstract class Animal(val name: String) {
abstract fun sound(): String
fun describe() = "$name 发出 ${sound()} 声"
}
// 继承(类默认 final,需 open 才能继承)
open class Bird(name: String) : Animal(name), Flyable {
override fun sound() = "叽叽"
override fun fly() = println("$name 在飞翔")
}
Dart
// 接口(Dart 中每个类都隐式是接口)
abstract class Flyable {
void fly();
void land() => print("降落"); // 默认实现
}
// 抽象类
abstract class Animal {
final String name;
Animal(this.name);
String sound();
String describe() => "$name 发出 ${sound()} 声";
}
// 继承(extends)+ 实现(implements)
class Bird extends Animal implements Flyable {
Bird(super.name);
@override String sound() => "叽叽";
@override void fly() => print("$name 在飞翔");
@override void land() => print("鸟儿降落");
}
TypeScript
// 接口
interface Flyable {
fly(): void;
land?(): void; // 可选方法
}
// 抽象类
abstract class Animal {
constructor(public name: string) {}
abstract sound(): string;
describe(): string { return `${this.name} 发出 ${this.sound()} 声`; }
}
// 继承 + 实现接口
class Bird extends Animal implements Flyable {
sound(): string { return "叽叽"; }
fly(): void { console.log(`${this.name} 在飞翔`); }
}
11. 数据类
💡 数据类自动生成
equals、hashCode、toString、copy
Kotlin
data class User(
val id: Int,
val name: String,
val email: String
)
val user1 = User(1, "张三", "z@qq.com")
val user2 = user1.copy(name = "李四") // 拷贝并修改
println(user1 == user2) // false(按值比较)
println(user1) // User(id=1, name=张三, email=z@qq.com)
Dart
// Dart 没有内置数据类,需要手动实现或用 freezed 包
class User {
final int id;
final String name;
final String email;
const User({required this.id, required this.name, required this.email});
// 需手动写 copyWith
User copyWith({int? id, String? name, String? email}) =>
User(id: id ?? this.id, name: name ?? this.name, email: email ?? this.email);
@override
String toString() => "User(id: $id, name: $name)";
}
// 推荐使用 freezed 包自动生成 ✅
TypeScript
// TS 没有数据类概念,用 interface 或 type 定义结构
interface User {
id: number;
name: string;
email: string;
}
const user1: User = { id: 1, name: "张三", email: "z@qq.com" };
// 拷贝并修改(展开运算符)
const user2: User = { ...user1, name: "李四" };
// 比较(TS/JS 对象比较是引用,不是值!)
console.log(user1 === user2); // false(不同引用)
12. Lambda 与高阶函数
Kotlin
// Lambda 基本语法
val double = { x: Int -> x * 2 }
val add: (Int, Int) -> Int = { a, b -> a + b }
// 函数类型作参数
fun operate(a: Int, b: Int, op: (Int, Int) -> Int) = op(a, b)
val result = operate(3, 4) { a, b -> a + b } // 尾随 Lambda
// it 关键字(单参数 Lambda 的隐式名)
listOf(1, 2, 3).map { it * 2 }
Dart
// 箭头函数(单行)
var double = (int x) => x * 2;
// 匿名函数(多行)
var add = (int a, int b) {
return a + b;
};
// 函数类型参数
int operate(int a, int b, int Function(int, int) op) => op(a, b);
var result = operate(3, 4, (a, b) => a + b);
// 集合操作
[1, 2, 3].map((x) => x * 2).toList();
TypeScript
// 箭头函数
const double = (x: number) => x * 2;
const add = (a: number, b: number) => a + b;
// 函数类型参数
function operate(a: number, b: number, op: (a: number, b: number) => number) {
return op(a, b);
}
const result = operate(3, 4, (a, b) => a + b);
// 集合操作
[1, 2, 3].map(x => x * 2);
13. 扩展函数/方法
💡 给已有类添加新方法,不修改原类!Dart/TS 叫扩展方法
Kotlin
// 给 String 扩展一个方法
fun String.isPalindrome(): Boolean =
this == this.reversed()
// 使用
println("racecar".isPalindrome()) // true
println("hello".isPalindrome()) // false
Dart
// extension 关键字(Dart 2.7+)
extension StringExtension on String {
bool isPalindrome() => this == split('').reversed.join();
}
// 使用
print("racecar".isPalindrome()); // true
TypeScript
// TS 不支持扩展方法,通过原型扩展(不推荐)
// 更好的方式是工具函数
function isPalindrome(s: string): boolean {
return s === s.split('').reverse().join('');
}
// 或者用模块扩展(Declaration Merging)
declare global {
interface String {
isPalindrome(): boolean;
}
}
String.prototype.isPalindrome = function() {
return this === this.split('').reverse().join('');
};
14. 异步编程
💡 三者都支持 async/await,是目前最主流的异步写法!
Kotlin
import kotlinx.coroutines.*
// 挂起函数
suspend fun fetchUser(id: Int): User {
delay(1000) // 模拟网络请求
return User(id, "张三")
}
// 使用协程
fun main() = runBlocking {
val user = fetchUser(1) // 像同步一样写
println(user.name)
// 并发
val deferred1 = async { fetchUser(1) }
val deferred2 = async { fetchUser(2) }
val users = listOf(deferred1.await(), deferred2.await())
}
Dart
// Future = 异步操作
Future<String> fetchUser(int id) async {
await Future.delayed(Duration(seconds: 1)); // 模拟网络请求
return "张三";
}
// 使用 async/await
void main() async {
String user = await fetchUser(1); // 像同步一样写
print(user);
// 并发(Future.wait)
var users = await Future.wait([fetchUser(1), fetchUser(2)]);
}
TypeScript
// Promise = 异步操作
async function fetchUser(id: number): Promise<string> {
await new Promise(resolve => setTimeout(resolve, 1000));
return "张三";
}
// 使用 async/await
async function main() {
const user = await fetchUser(1); // 像同步一样写
console.log(user);
// 并发(Promise.all)
const users = await Promise.all([fetchUser(1), fetchUser(2)]);
}
异步对比总览
| 概念 | Kotlin | Dart | TypeScript |
|---|---|---|---|
| 异步单值 | Deferred<T> | Future<T> | Promise<T> |
| 异步流 | Flow<T> | Stream<T> | Observable<T>(RxJS) |
| 关键字 | suspend / async | async / await | async / await |
| 并发 | async { } + await | Future.wait([]) | Promise.all([]) |
| 错误处理 | try-catch | try-catch | try-catch |
15. 枚举
Kotlin
// 简单枚举
enum class Direction { NORTH, SOUTH, EAST, WEST }
// 带属性和方法的枚举
enum class Planet(val mass: Double) {
EARTH(5.97e24),
MARS(6.42e23);
fun gravity() = mass / 1e24
}
val d = Direction.NORTH
println(d.name) // "NORTH"
println(d.ordinal) // 0
Dart
// 简单枚举
enum Direction { north, south, east, west }
// 增强枚举(Dart 2.17+,支持属性和方法)
enum Planet {
earth(5.97e24),
mars(6.42e23);
final double mass;
const Planet(this.mass);
double gravity() => mass / 1e24;
}
var d = Direction.north;
print(d.name); // "north"
print(d.index); // 0
TypeScript
// 数字枚举
enum Direction { NORTH, SOUTH, EAST, WEST } // 0, 1, 2, 3
// 字符串枚举(推荐,可读性好)
enum Direction {
NORTH = "NORTH",
SOUTH = "SOUTH",
}
// 联合类型也常用于代替枚举
type Direction = "NORTH" | "SOUTH" | "EAST" | "WEST";
const d: Direction = "NORTH";
16. 类型判断与转换
Kotlin
val x: Any = "Hello"
// is 判断类型(智能转换!)
if (x is String) {
println(x.length) // 自动转为 String,无需手动转换 ✨
}
// as 强制转换
val s = x as String
// as? 安全转换(失败返回 null)
val s2 = x as? Int // null(因为 x 是 String)
Dart
dynamic x = "Hello";
// is 判断
if (x is String) {
print(x.length); // Dart 也支持智能转换 ✨
}
// as 强制转换
String s = x as String;
// 没有安全转换操作符,用 try-catch 代替
TypeScript
const x: unknown = "Hello";
// typeof(基本类型判断)
if (typeof x === "string") {
console.log(x.length); // 类型收窄 ✨
}
// instanceof(对象类型判断)
if (x instanceof Array) { ... }
// 类型断言(as)
const s = x as string;
// 类型守卫函数
function isString(val: unknown): val is string {
return typeof val === "string";
}
17. 解构赋值
Kotlin
// 数据类解构(通过 componentN 方法)
data class Point(val x: Int, val y: Int)
val (x, y) = Point(10, 20)
// List 解构
val (first, second) = listOf(1, 2, 3)
// Map 解构
val map = mapOf(1 to "a", 2 to "b")
for ((key, value) in map) {
println("$key -> $value")
}
Dart
// Dart 3.0+ 支持模式匹配和解构 🎉
var (x, y) = (10, 20); // Record 解构
// List 解构
var [first, second, ...rest] = [1, 2, 3, 4];
// Map 解构
var {"name": name, "age": age} = {"name": "张三", "age": 18};
TypeScript
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4];
// 对象解构
const { name, age } = { name: "张三", age: 18 };
// 重命名
const { name: userName, age: userAge = 0 } = user; // 含默认值
// 函数参数解构
function greet({ name, age }: { name: string; age: number }) {
console.log(`${name}, ${age} 岁`);
}
18. 模块与导入
Kotlin
// 导入类
import com.example.User
import com.example.* // 通配符导入
// 别名
import com.example.User as AppUser
// 顶层函数直接导入
import com.example.utils.formatDate
Dart
// 导入包
import 'package:flutter/material.dart';
import 'dart:async'; // 内置库
// 导入本地文件
import 'utils/helper.dart';
// 别名
import 'package:foo/bar.dart' as Bar;
// 只导入部分
import 'package:math/math.dart' show sqrt, pi;
// 排除部分
import 'package:foo/foo.dart' hide BadClass;
TypeScript
// 命名导入
import { User, formatDate } from './utils';
// 默认导入
import React from 'react';
// 全部导入 + 别名
import * as Utils from './utils';
// 混合
import React, { useState, useEffect } from 'react';
// 类型导入(只用于类型检查,编译后删除)
import type { User } from './types';
🎓 总结速查表
| 特性 | Kotlin | Dart | TypeScript |
|---|---|---|---|
| 文件扩展名 | .kt | .dart | .ts |
| 语句结尾 | 无分号 | 有分号 ; | 有分号(可选) |
| 空安全 | ? / !! | ? / ! | | null / ! |
| 字符串插值 | ${} 双引号 | ${} 普通引号 | ${} 反引号 |
| 函数类型 | (Int) -> Int | int Function(int) | (n: number) => number |
| 异步关键字 | suspend | async | async |
| 主要用途 | Android / 后端 | Flutter / 全平台 | 前端 / Node.js |
📚 推荐资源
- Kotlin 官方文档:https://kotlinlang.org/docs
- Dart 官方文档:https://dart.dev/guides
- TypeScript 官方文档:https://www.typescriptlang.org/docs
💬 学习建议:语言是工具,核心是思想。掌握了 Kotlin,学 Dart 大约需要 1-2 周,学 TypeScript 大约需要 3-5 天。加油!🎉