主题
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.FULL→Stack布局 +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.AVMediaKit的media.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 上逐项验证