使用AI开发鸿蒙项目必要的语言约束

由于目前大部分的AI模型在开发鸿蒙项目时经常会将ArkTS语言用成TS语言,因此我们需要在项目开发时进行语言约束,以下是我整理的相关内容以及约束清单。

ArkTS 相比 TS 特性差异

ArkTS 通过规范约束了 TS 中过于灵活而影响开发正确性或者给运行时带来不必要额外开销的特性,下面通过代码片段说明部分约束特性。

1. 不支持在运行时更改对象布局

// TypeScript代码片段
class Point {
  public x: number;
  public y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}
// case1
let p1 = new Point(1.0, 1.0);
delete p1.x; // 在ArkTS中,编译时错误,不允许删除属性
// case2
let p2 = new Point(2.0, 2.0);
p2.z = 2.0; // 在ArkTS中,编译时错误,不允许添加属性
// case3
let p3 = new Point(3.0, 3.0);
p3.x = 'Hello!'; // 在ArkTS中,编译时错误,不允许赋值其他类型

以上 TS 代码片段展示了如何在运行时通过添加和删除某些属性来更改对象的布局。运行时支持此类特性需要大量的性能开销,ArkTS 不支持在运行时更改对象的布局。

在 ArkTS 中,可以使用可选属性和给该属性赋值 undefined 的方式来替代。

2. 对象字面量须标注类型

// TypeScript代码片段
const point = {
  x: 0,
  y: 0,
};

以上 TS 代码片段展示了没有类型的场景。如果编译器不知道变量 point 的确切类型,由于对象布局不能确定,编译器无法深度地优化这段代码,造成性能瓶颈。没有类型也会造成属性的类型缺少限制,例如 point.x 的类型在此时为 number,它也可以被赋值成其他类型,造成额外的运行时检查和开销。

在 ArkTS 中,需要为对象字面量标注类型。

// ArkTS代码片段
interface Point {
  x: number;
  y: number;
}
const point: Point = {
  x: 0,
  y: 0,
};

3. 不支持 structural typing

// TypeScript代码
class C {
  s: string = "";
}
class D {
  n: number = 0;
  s: string = "";
}
function foo(c: C) {
  console.log(c.s);
}
foo(new D()); // 在ArkTS中,编译时错误,不支持 structural typing

以上 TS 代码片段展示了 structural typing 特性。在 ArkTS 已经采用了 nominal typing 类型系统的前提下,如果额外支持 structural typing 给语言实现和开发者均会带来不必要的复杂度。在示例中,foo 虽然声明参数类型是 C,但也可以传递类型 D 的变量,这种灵活性可能不符合开发者的意图,容易带来程序行为的正确性问题。另外,由于类型 D 和类型 C 布局不同,那么 foo 中对 c.s 这个属性访问就不能被优化成根据固定偏移量访问的方式,从而给运行时性能造成瓶颈。


语言约束 Do/Don’t 清单

  • Don’t:

    • 运行时删除或新增对象属性(例如 delete obj.propobj.newProp = ...)。
    • 给属性赋与声明类型不一致的值(例如 prop: number 却赋 string)。
    • 使用 any 或宽泛的 unknown 作为逃逸手段绕过类型检查。
    • 依赖 structural typing 的兼容性来通过类型检查。
    • 依赖运行时反射式访问改变对象布局或绕过类型约束。
  • Do:

    • 所有对象字面量必须显式标注类型(如 const p: Point = { ... })。
    • 需要扩展属性时使用可选属性(z?: number)或以 undefined 表示缺失。
    • 按 nominal typing 设计类型,避免跨类型“形状相同即可”的滥用。
    • 保持构造与方法调用的一致代码风格与半角符号。

推荐替代示例

  • 用可选属性替代动态添加:
interface Point { x: number; y: number; z?: number }
const p: Point = { x: 1, y: 2 };
p.z = 3; // 合规
  • 对象字面量显式类型:
interface Point { x: number; y: number }
const point: Point = { x: 0, y: 0 };

性能与可优化布局说明(简版)

  • ArkTS 倾向于在编译期确定对象布局,便于 JIT/AOT 将属性访问优化为固定偏移读取,减少运行时检查。
  • 运行时增删属性或依赖宽泛类型会破坏稳定布局,导致额外的类型判断与慢路径,增加开销并影响可预测性能。

开发/评审检查清单

  • 是否存在对象属性的运行时增删?
  • 所有对象字面量是否显式标注类型?
  • 是否避免使用 any/unknown 作为逃逸手段?
  • 是否避免依赖 structural typing 进行跨类型传参?
  • 代码风格是否统一(半角符号、调用格式一致)?
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐