【HarmonyOS开发小实践】ArkTS 从 TypeScript 到方舟语言的演进
写 HarmonyOS 应用,绕不开 ArkTS。它是华为给 HarmonyOS 选定的官方高级语言,从 TypeScript 扩展而来,又加了一层静态类型约束和状态管理能力。很多前端同学第一次看到 ArkTS 代码会觉得眼熟,写起来又会发现有些地方跟 TS 不太一样。这篇就把 ArkTS 的定位、它从 TS 演进过来的路径、以及它和 ArkUI 的关系捋清楚。
ArkTS 的定位:HarmonyOS 应用的官方语言
HarmonyOS 应用开发不止一种语言可选,但 ArkTS 是官方主推的那一个。它的定位很明确:给 HarmonyOS 应用开发用的官方高级语言。
这个定位意味着两件事:
第一,ArkTS 是面向应用开发的语言,不是系统级语言。写驱动、写底层服务不是它的活儿,那是 C/C++ 的地盘。ArkTS 写的是应用层的 UI、业务逻辑、数据交互。
第二,它是"高级语言",带类型系统、带装饰器、带完整的工程化能力。不是脚本语言的定位,而是一套有编译工具链、有运行时、有完整生态的语言。
ArkTS 在 TypeScript 生态基础上做了进一步扩展,保持了 TS 的基本风格,同时通过规范定义强化开发期静态检查和分析,提升代码健壮性,并实现更好的程序执行稳定性和性能。
从 TypeScript 到 ArkTS 的演进路径
要理解 ArkTS,得先看它从 TS 演进过来的脉络。这个演进不是推倒重来,而是在 TS 基础上做加减法。
演进的核心思路有三条:
第一条,强化静态类型。 TS 的类型系统是可选的,可以写 any,可以关闭严格检查,可以用 @ts-ignore 跳过类型检查。ArkTS 把这些口子都堵上了。any 不让用,unknown 不让用,@ts-ignore 不让用,严格类型检查不是可配置项而是强制的。这么做是为了让编译器能在编译期就把类型问题查出来,减少运行时开销。
第二条,加入状态管理和 UI 描述能力。 TS 是纯语言,不关心 UI。ArkTS 引入了一套装饰器体系,@State、@Prop、@Link、@Component、@Entry 这些,专门用来描述 UI 组件和组件间的状态同步。这是 ArkTS 区别于 TS 最明显的地方。
第三条,增强并发能力。 TS/JS 的并发能力支持有限,主要靠 Promise 和 async/await,真正的多线程并发(Worker)用起来比较重。ArkTS 在这基础上加了 TaskPool 和 Worker 两套并发 API,还提出了 Sendable 概念来支持对象在并发实例间的引用传递,提升并发通信性能。
ArkTS 的核心特性
把 ArkTS 摊开看,核心特性有这么几块:
静态类型与严格检查
ArkTS 强制静态类型,编译期就把类型确定下来。这跟 TS 的"渐进式类型"不一样,TS 的类型是给你看的,编译完就擦除了;ArkTS 的类型会参与到编译优化和运行时性能里。
// ArkTS 中不能写 any
// let value: any = 42; // 编译报错
// 必须显式标注类型,或者让编译器能推断出来
let value: number = 42;
let name: string = 'ArkTS';
// 对象字面量要标注类型
class UserInfo {
public name: string = '';
public age: number = 0;
}
let user: UserInfo = { name: '张三', age: 28 };
状态管理装饰器
这是 ArkTS 最有特色的部分。一套装饰器描述 UI 组件的状态和关系:
@Entry
@Component
struct Counter {
@State count: number = 0; // 状态变量,变化会触发 UI 刷新
build() {
Column() {
Text(`点击次数: ${this.count}`)
.fontSize(20)
Button('加一')
.onClick(() => {
this.count++;
})
}
}
}
@State 标记的变量一变,依赖它的 UI 自动刷新。@Prop 做单向同步,@Link 做双向同步。这套机制让 UI 和状态绑定在一起,不用手动调 refresh。
并发能力增强
ArkTS 提供了 TaskPool 和 Worker 两种并发 API,还引入了 Sendable 概念:
import { taskpool } from '@kit.ArkTS';
@Concurrent
function heavyCompute(data: number[]): number {
// 在子线程跑的耗时计算
return data.reduce((sum, n) => sum + n, 0);
}
// 主线程调用
let task = new taskpool.Task(heavyCompute, [1, 2, 3, 4, 5]);
taskpool.execute(task).then((result: Object) => {
console.info(`计算结果: ${result}`);
});
基础类库增强
ArkTS 的基础类库和容器类库比标准 TS 更丰富,提供了高精度数学库 Decimal、Buffer 与 FastBuffer、XML 处理、多种容器库等能力。这些是写应用时常用的工具,官方给你备好了。
与 ArkUI 的关系
ArkTS 和 ArkUI 经常一起出现,容易搞混两者的关系。简单说:ArkTS 是语言,ArkUI 是框架。
ArkUI 是 HarmonyOS 的 UI 开发框架,提供了一套声明式的 UI 描述语法。这套语法的载体就是 ArkTS。你在 ArkTS 代码里写的 build() 方法、Column()、Text()、Button() 这些,就是 ArkUI 提供的组件和 API。
// 这段代码里,ArkTS 提供语言能力,ArkUI 提供 UI 组件
@Entry
@Component
struct MyPage {
@State message: string = 'Hello';
build() { // ArkUI 的组件构建方法
Column() { // ArkUI 的布局组件
Text(this.message) // ArkUI 的文本组件
.fontSize(16)
}
}
}
两者的分工是:ArkTS 负责类型系统、状态管理装饰器、语言语义;ArkUI 负责组件体系、布局算法、渲染管线。状态管理装饰器(@State 等)是 ArkTS 语言层面的能力,但服务的对象是 ArkUI 的 UI 刷新机制。
与 TS/JS 的互操作
ArkTS 支持与 TS/JS 高效互操作。这意味着你可以复用已有的 TS/JS 代码库,不用全部重写。互操作的场景包括:
- 在 ArkTS 项目里引用 TS/JS 模块
- ArkTS 代码调用 TS/JS 导出的函数
- TS/JS 代码调用 ArkTS 导出的 API
不过互操作有边界。跨语言调用会有一定开销,性能敏感的路径不建议频繁跨语言。另外 ArkTS 的静态类型约束在互操作时仍然生效,从 TS/JS 那边拿到的数据要符合 ArkTS 的类型要求。
编译运行:从源码到执行
ArkTS 代码写完,是怎么跑起来的?这背后是方舟编译运行时(ArkCompiler)在干活。ArkCompiler 分两部分:
ArkTS 编译工具链负责把高级语言编译成方舟字节码文件(*.abc)。ArkTS 运行时负责在设备侧运行字节码文件,执行程序逻辑。运行时里有解释器、AOT 编译器、JIT 编译器等多种执行方式,根据场景选择最优路径。
这块的细节后面有专门的文章展开讲,这里先知道个大概:ArkTS 代码不是直接解释执行的,会先编译成字节码,再由运行时根据热点情况决定解释执行还是编译执行。
一个完整的 ArkTS 组件示例
把前面讲的特性串起来看一个完整的例子。这是一个带状态管理、异步请求、列表渲染的组件:
import { taskpool } from '@kit.ArkTS';
// 数据模型
class TodoItem {
public id: number = 0;
public title: string = '';
public done: boolean = false;
}
// 模拟异步数据加载
@Concurrent
function fetchTodos(): TodoItem[] {
// 实际场景里这里会是网络请求或数据库查询
let result: TodoItem[] = [];
for (let i = 1; i <= 5; i++) {
let item: TodoItem = { id: i, title: `任务 ${i}`, done: false };
result.push(item);
}
return result;
}
@Entry
@Component
struct TodoListPage {
@State todos: TodoItem[] = [];
@State loading: boolean = false;
aboutToAppear() {
this.loadTodos();
}
async loadTodos() {
this.loading = true;
try {
let task = new taskpool.Task(fetchTodos);
let result = await taskpool.execute(task) as TodoItem[];
this.todos = result;
} catch (e) {
console.error(`加载失败: ${e}`);
} finally {
this.loading = false;
}
}
build() {
Column() {
if (this.loading) {
Text('加载中...')
.fontSize(16)
} else {
ForEach(this.todos, (item: TodoItem) => {
Row() {
Text(item.title)
.fontSize(16)
.layoutWeight(1)
Toggle({ type: ToggleType.Checkbox, isOn: item.done })
.onChange((isOn: boolean) => {
item.done = isOn;
})
}
.padding(12)
}, (item: TodoItem) => item.id.toString())
}
}
}
}
这段代码里用到了 ArkTS 的多个特性:类定义和静态类型、@State 状态管理、@Concurrent 标记并发函数、TaskPool 异步执行、async/await 异步语法、ArkUI 的组件和布局。一个文件里把这些串起来,就是典型的 ArkTS 应用代码组织方式。
ArkTS 的演进方向
ArkTS 不是定死不变的。官方文档里提到,未来会结合应用开发和运行的需求持续演进,逐步提供并发能力增强、系统类型增强、分布式开发范式等更多特性。
从现在的形态看,ArkTS 的设计取向很明确:宁可限制一些灵活性,也要换来性能和稳定性。这个取向跟 HarmonyOS 的设备场景有关——HarmonyOS 要跑在从手机到穿戴到车机等各种设备上,性能和稳定性比语言灵活性更重要。理解了这个取向,就能理解 ArkTS 为什么做了那些限制。
小小总结
别把 ArkTS 当 TS 写。 语法像不代表习惯能照搬。ArkTS 的类型约束更严,any 不能用,对象字面量要标类型,解构赋值不支持。从 TS 项目迁过来要先过类型检查这一关。
状态管理装饰器是 ArkTS 的核心。 写 HarmonyOS 应用,@State、@Prop、@Link 这套机制要吃透。它不是可选的语法糖,而是 ArkUI 刷新 UI 的基础。理解了状态变量的依赖追踪,才能写出性能好的组件。
并发能力按场景选。 简单的 I/O 异步用 Promise/async/await 就够;CPU 密集的短任务用 TaskPool;长时间运行的后台任务用 Worker。别一上来就 Worker,杀鸡用牛刀。
互操作不是免费的。 ArkTS 调 TS/JS 有跨语言开销,热点路径别频繁跨。能纯 ArkTS 实现的逻辑就别混着写。
官方文档要常看。 ArkTS 还在演进,特性在增,限制在调。写代码遇到编译报错先查文档,可能是某个特性被限制了,也可能是新版本有更好的写法。
更多推荐



所有评论(0)