跳转到内容

HarmonyOS ArkTS 严格模式迁移经验

结论:把 Web/Electron 项目迁移到 HarmonyOS NEXT(API 23)Stage 模型时,最大的成本不是 API 差异,而是 ArkTS 严格模式。它禁止 any、展开运算符、未类型化对象字面量、catch 类型标注等 TS 常规写法,编译错误集中在少数几类,逐一替换即可通过构建。

适用范围与环境

  • 目标设备:HarmonyOS 6.1 / API 23 华为手机(真机调试)
  • 开发工具:DevEco Studio(SDK 位于 D:\software\Huawei\devecostudio\DevEco Studio\sdk
  • 项目:AlgerMusicPlayer-homeng(Electron 音乐播放器 → Stage/ArkTS HAP 移植)

命令行构建环境

Windows PowerShell 下用 hvigor 命令行构建前,需要临时设置环境变量:

powershell
$env:DEVECO_SDK_HOME = "D:\software\Huawei\devecostudio\DevEco Studio\sdk"
$env:Path = "D:\software\Huawei\devecostudio\DevEco Studio\tools\hvigor\bin;" +
            "D:\software\Huawei\devecostudio\DevEco Studio\tools\ohpm\bin;" +
            "D:\software\Huawei\devecostudio\DevEco Studio\tools\node;" +
            "D:\env\node\node-v26.1.0-win-x64;$env:Path"
cd D:\data\project\AlgerMusicPlayer-homeng
hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemon

构建输出中 hvigor TYPE CHECK SUCCESSFUL 表示类型检查通过;Failed :entry:default@CompileArkTS 表示还有 ArkTS 规则错误。

ArkTS 严格模式高频错误与修复

以下按实际项目中遇到频率排序(已验证修复):

1. catch 子句不允许类型标注(arkts-no-types-in-catch)

ts
// 错误
} catch (error: BusinessError) {

// 正确
} catch (error) {

catch 变量隐式推断,需要区分错误类型时用 instanceof 或字段判断收窄。BusinessError 仍可用于回调参数(如 player.on('error', (error: BusinessError) => ...)),仅 catch 子句受限。

2. 对象字面量必须对应显式声明的类或接口(arkts-no-untyped-obj-literals)

ts
// 错误:const settings = { ... } 局部推断
const settings = { quality: 'high' };

// 正确:显式标注类型
const settings: AppSettings = { quality: 'high' };

3. 字面量联合类型与 string 不兼容

ts
// this.quality 是 string,不能赋给 'standard' | 'lossless' | 'high'
// 方案:把字段类型改成联合字面量,或经 switch 转换

推荐直接改字段声明为联合字面量类型,避免运行时校验。

4. 禁止展开运算符([...queue])

ts
// 错误
[...queue]
// 正确
queue.slice()
[song, ...this.queue]  // 改为
[song].concat(this.queue)

5. 禁止未类型化的回调参数

ForEach 回调、map 回调等必须显式标注参数类型:

ts
ForEach(this.playlists, (pl: Playlist) => { ... })
artistNames.map((a: SearchArtist) => a.name)

6. 禁止 as const

ts
// 错误
const themeValue = 'auto' as const;
// 正确
const themeValue: 'auto' | 'light' | 'dark' = 'auto';

7. 布局 API 替换

  • bindContentSheet + SheetSize.FULLStack 布局 + if (this.showFullPlayer) { this.FullPlayer() }
  • .onToggle(...).onChange((isOn: boolean) => ...)
  • Promise.all([...]) 解构赋值 → 分开 await 声明

8. 模块导入用 @kit 命名空间

ts
import { common } from '@kit.AbilityKit';
import { media } from '@kit.AVMediaKit';

不要从 @ohos.* 旧路径导入已迁移的模块。

迁移要点(Web → ArkTS)

  • 所有共享状态类(Store/Service)保持单例导出:export const playerStore = new PlayerStoreClass();
  • 播放器用 @kit.AVMediaKitmedia.AVPlayer,异步方法(prepare/play/pause/seek)要防竞态:用 generation 计数器,旧播放器完成时丢弃回调
  • 网络请求用 @kit.NetworkKit 的 http,返回结构先定义 model 类再解析,天然满足 ArkTS 对象字面量规则

验证

  • 构建通过:hvigorw assembleHap ... --no-daemon 结束于 BUILD SUCCESSFUL,生成 entry/build/default/outputs/default/entry-default-unsigned.hap
  • 真机安装:DevEco Studio 配好签名后直接 Run,或 hdc install <hap>
  • 分层验收:代码存在 → HAP 构建成功 → 安装启动成功 → 条件 UI 可见 → 实际播放成功

已知未验证边界

  • UI 性能(按钮点击延迟、整页重绘)在真机上的实测数据未固化,静态审查建议优先排查列表 ForEach 的 key 生成与 bindSheet 场景
  • 后台播放、锁屏控制等能力需在真机 API 23 上逐项验证

基于 MIT 许可发布