HarmonyOS鸿蒙Next中关于interface的奇怪问题
HarmonyOS鸿蒙Next中关于interface的奇怪问题
import { speechRecognizer } from '@kit.CoreSpeechKit';
let setListener: speechRecognizer.RecognitionListener = {
onStart(sessionId: string, eventMessage: string) {
console.info(`onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`);
},
onEvent(sessionId: string, eventCode: number, eventMessage: string) {
console.info(`onEvent, sessionId: ${sessionId} eventCode: ${eventCode} eventMessage: ${eventMessage}`);
},
onResult(sessionId: string, result: speechRecognizer.SpeechRecognitionResult) {
console.info(`onResult, sessionId: ${sessionId} sessionId: ${JSON.stringify(result)}`);
},
onComplete(sessionId: string, eventMessage: string) {
console.info(`onComplete, sessionId: ${sessionId} eventMessage: ${eventMessage}`);
},
onError(sessionId: string, errorCode: number, errorMessage: string) {
console.error(`onError, sessionId: ${sessionId} errorCode: ${errorCode} errorMessage: ${errorMessage}`);
},
}
上面的代码是正确的。
如果我自定义一个一模一样的speechRecognizer就不行了,代码如下:
// import { speechRecognizer } from '@kit.CoreSpeechKit';
declare namespace speechRecognizer {
export interface RecognitionListener {
onStart(sessionId: string, eventMessage: string): void;
onEvent(sessionId: string, eventCode: number, eventMessage: string): void;
onResult(sessionId: string, result: SpeechRecognitionResult): void;
onComplete(sessionId: string, eventMessage: string): void;
onError(sessionId: string, errorCode: number, errorMessage: string): void;
}
export interface SpeechRecognitionResult {
isFinal: boolean;
isLast: boolean;
result: string;
}
}
let setListener: speechRecognizer.RecognitionListener = {
onStart(sessionId: string, eventMessage: string) {
console.info(`onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`);
},
onEvent(sessionId: string, eventCode: number, eventMessage: string) {
console.info(`onEvent, sessionId: ${sessionId} eventCode: ${eventCode} eventMessage: ${eventMessage}`);
},
onResult(sessionId: string, result: speechRecognizer.SpeechRecognitionResult) {
console.info(`onResult, sessionId: ${sessionId} sessionId: ${JSON.stringify(result)}`);
},
onComplete(sessionId: string, eventMessage: string) {
console.info(`onComplete, sessionId: ${sessionId} eventMessage: ${eventMessage}`);
},
onError(sessionId: string, errorCode: number, errorMessage: string) {
console.error(`onError, sessionId: ${sessionId} errorCode: ${errorCode} errorMessage: ${errorMessage}`);
},
}
就会提示:
Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals) <ArkTSCheck>
为什么import系统的可以,我自己定义的就不行呢?
更多关于HarmonyOS鸿蒙Next中关于interface的奇怪问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中关于interface的奇怪问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
分析的很详细,
仔细观察一下,和系统的有什么区别呢,系统的声明是在**.d.ts里面,然后我也跟着做,把
declare namespace speechRecognizer
放在一个.d.ts文件声明,再导入,也可以。
在HarmonyOS Next中,interface主要用于定义Ability、ExtensionAbility等组件间的通信接口,支持TypeScript/ArkTS声明。其实现需遵循严格的API版本兼容性,且部分接口可能受系统权限或设备类型限制。若遇到接口未定义或调用异常,需检查API版本、权限声明及设备支持列表。
在HarmonyOS Next的ArkTS中,arkts-no-untyped-obj-literals 规则禁止使用未显式声明类型(类或接口)的对象字面量。你的自定义 declare namespace 代码在编译时,ArkTS编译器可能无法将对象字面量 { onStart(...), ... } 直接推断为与你的 speechRecognizer.RecognitionListener 接口匹配。
这是因为 declare namespace 仅提供类型声明,而 import 导入的模块除了类型,还可能包含运行时的具体实现或元信息,帮助编译器完成类型推断。要解决此问题,你有以下几种方案:
-
显式类型转换:创建对象字面量后,使用
as将其断言为你的接口类型。let setListener: speechRecognizer.RecognitionListener = { onStart(sessionId: string, eventMessage: string) { console.info(`onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`); }, // ... 其他方法 } as speechRecognizer.RecognitionListener; // 添加类型断言 -
实现类:定义一个明确实现该接口的类。
class MyRecognitionListener implements speechRecognizer.RecognitionListener { onStart(sessionId: string, eventMessage: string): void { console.info(`onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`); } // ... 实现其他接口方法 } let setListener: speechRecognizer.RecognitionListener = new MyRecognitionListener(); -
使用对象字面量并赋值给变量:先声明一个符合接口类型的变量,再分别赋值其方法(虽然代码稍长,但可绕过此检查)。
let setListener: speechRecognizer.RecognitionListener = { onStart: (sessionId: string, eventMessage: string) => { console.info(`onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`); }, // ... 其他方法以同样的箭头函数形式定义 };
根本原因:ArkTS是静态类型语言,对类型安全要求严格。import 的模块经过编译器特殊处理,能提供足够的类型上下文;而自定义的 declare namespace 在纯类型层面,对象字面量的初始化可能触发类型推断不足,因此需通过上述方式明确类型。

