hi 大家好,我是 DHL。就职于美团、快手、小米。公众号:ByteCode,分享有用的原创文章,涉及鸿蒙、Android、Java、Kotlin、性能优化、大厂面经
我最近建了一个鸿蒙开发者交流群,群里有大佬说在 gitee 鸿蒙仓库中可以下载 DevEco Studio 4.0。于是我下载体验了一下,运行了官方提供示例项目 Shopping 出现了 422 个 Error 级别的错误,导致项目根本无法编译,于是我把这 422 个 Error 级别的错误 从头到尾改了一遍,可以理解为,我把核心代码重写了一遍,后面我会分享在 github 上。
出现这些错误的原因是因为 DevEco Studio 4.0 有一个非常重要的更新,进行代码编译时会对不符合 ArkTS 语法规则的代码进行告警。
告警分为两个级别:错误、警告。
- 错误(Error): 必须要遵的规范。如果不遵从规范,将会导致程序编译失败
- 警告(Warning): 推荐遵从的规范,尽管现在违反该规范不会影响编译流程,但是在将来,违反该规范可能将会导致程序编译失败,所以尽量遵守规范
这个更新既是开发者福音,有是开发者的噩梦,好处在于从编译器层面对开发规范进行了强制约束,有助于提高代码的可靠性和可维护性。可以帮助开发者编写更加健壮和可靠的代码。但是不好的一点,因为 TypeScript 的语言非常的自由,如果你没有按照社区的规范去写,那么升级到 DevEco Studio 4.0 你将面临大量的语法适配工作。
鸿蒙官方提供的示例 Shopping 就是一个经典的反面教材,导入 DevEco Studio 4.0 中运行出现了 422 个 Error 级别的错误。
ArkTS 是在 TypeScript 的基础上扩展的,而 TypeScript 是在 JavaScript 的基础上扩展的,为了兼容 JavaScript,TypeScript 在很多方面都做了妥协。如果是移动端开发者,首次接触 TypeScript 和 JavaScript 的项目的时候,会觉得项目代码乱七八糟的,
核心原因 JavaScript 是非常的灵活的语言,开发者可以按照自己的想法去写,比如没有类型约束,一个变量可能初始化时是字符串,过一会儿又被赋值为数字,而 TypeScript 虽然提供了静态类型约束,但是不是强制的,从而导致了开发者可以按照自己的想法随意去写,只要项目可以运行起来就没有人会去改。
而鸿蒙在编译器层面上进一步加强了 ArkTS 语法规则的检查,有助于提高代码的可靠性和可维护性。帮助开发者编写更加健壮和可靠的代码。
ArkTS 限制了 TypeScript 很多逆天语法,这篇主要介绍我在运行官方示例项目 Shopping 遇到的错误,熟悉这些后,再运行官方示例项目,不用在去网上找答案了,当然你在网上也很难找到这些错误的解决方案。
本文所有代码都已经上传到了 github HarmonyPractice 仓库,欢迎点击 HarmonyPractice 仓库右上角 star,同时我也打开了 Discussions 功能,欢迎来 Discussions 一起讨论。
HarmonyPractice:https://github.com/hi-dhl/HarmonyPractice
不支持 any 或 unknown 类型,禁止使用 var
在 ArkTS 中要求强制使用静态类型,我在之前的文章 鸿蒙:5 分钟秒懂 ArkTs,不能错过的知识点解析 介绍过,没有看过的小伙伴可以去看一下。
如果能够推断出具体的类型,ArkTS 允许省略具体类型,否则需要指定具体类型,不然会报错。并且不能使用 any 和 unknown 类型。
为什么不能使用 any 和 unknown 类型,我举一个例子,以下代码在 TypeScript 中是可以运行的。
HarmonyPractice/Basic/entry/src/main/ets/syntax/TestType1. ts
示例1
let type: any
type = true;
type = 42;
示例2
getValue(type: any){
}
this.getValue(1)
this.getValue(true)
当你在看到这些代码的时候,不知心里作何感想,一个变量声明为 any 类型,初始可能是 boolean 类型,过一会儿又被赋值为数字,然而这些代码在 TypeScript 中是可以运行的。这种写法是非常的不安全,存在很大的安全隐患。
上面的示例,在 ArkTS 中是被允许的,编译器就会给你一个大大的错误提示。
所以在 ArkTS 中我们应该这么写:
HarmonyPractice/Basic/entry/src/main/ets/syntax/TestType2. ets
const type: number = 1; // or const type = 1
let bool: boolean = true; // or let bool = true
// 如果你不确定类型,可以使用 object
let ob: object = []
const
和 let
的原理和区别,以及在什么场景下使用,我在之前的文章 鸿蒙:5 分钟秒懂 ArkTs,不能错过的知识点解析 做了详细的介绍。
需要注意的是在 TypeScript 中可以使用 var
,但是不推荐,在 ArkTS 中禁止使用 var
。因为是用 var
会带来很多问题。
if (true) {
var message = "DHL";
}
console.log(message); // 输出 "DHL",而不是报错
我们希望运行上面的代码报错,但是在 TypeScript 中不仅不会报错,而且还会输出 "DHL",这是因为 var
声明的变量,在全局范围内都有效,因此在 if
语句外面也能获取到。
不支持解构赋值
解构赋值在 TypeScript 项目中非常的常见。解构赋值虽然方便,但是降低了代码的可读性和可维护性,先来看一个示例。示例中的代码在 TypeScript 中可以运行的。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Destruct1. ts
let [head, ...tail] = [1, 2, 3, 4];
我们先来解释一下这段代码,示例中使用解构赋值从数组 [1, 2, 3, 4]
中提取值。解构赋值的语法 [head, ...tail]
表示我们想要从数组中提取第一个元素赋给 head
,并将剩余的元素以数组的形式赋给 tail
。
因此,经过这行代码后,head
的值将是 1,而 tail
的值将是数组 [2, 3, 4]。解构赋值很方便,越方便越容易被开发者滥用,解构赋值可能会导致代码变得难以理解,尤其是复杂的嵌套结构,降低了代码的可读性和可维护性,因此在 ArkTS 禁止这样写,上面示例在 ArkTS 中会报错。
因此在 ArkTS 中我们应该这样写。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Destruct2. ets
const data: Number[] = [1, 2, 3, 4];
const len = data.length;
let head = data[0];
let tail: Number[] = [];
for (let i = 1; i < len; ++i) {
tail.push(data[i]);
}
更多示例,可以前往 github HarmonyPractice 仓库查看。
不支持参数解构的函数声明
函数的参数解构,在 TypeScript 项目中,也是非常的常见的写法,使用起来非常的方便。
HarmonyPractice/Basic/entry/src/main/ets/syntax/DestructParams1. ts
request({ location: [lat, lon], name: string}) {
// 在这个方法中,我们接收一个包含 location 和 name 属性的对象作为参数
// location 是一个数组,包含两个元素,分别是经度和纬度
// name 是一个字符串
}
testRequest() {
// 在这个方法中,我们调用了上面定义的 request 方法,并传入一个对象作为参数
this.request({ location: [10, 10], name: "DHL" })
}
我们先解释一下这段代码,在 testRequest
方法中,我们调用了 request
方法,并传入了一个包含 location
和 name
属性的对象作为参数。其中 location
是一个数组,包含经度和纬度,而 name
是一个字符串。
参数的解构虽然方便,但是导致的结果代码变得难以理解,因此在 ArkTS 禁止这样写,上面示例在 ArkTS 中会报错。
因此在 ArkTS 中我们应该这样写。
HarmonyPractice/Basic/entry/src/main/ets/syntax/DestructParams2. ets
request(location: number[], name: string) {
// location 是一个数组,包含两个元素,分别是经度和纬度
// name 是一个字符串
}
testRequest() {
// 在这个方法中,我们调用了上面定义的 request 函数,并传入一个对象作为参数
this.request([10, 10], "DHL")
}
不支持在 catch 语句标注类型
在 ArkTS 中要求强制使用静态类型,如果能够推断出具体的类型,ArkTS 允许省略具体类型,否则需要指定具体类型。但是 catch 语句中有点不一样,先看示例代码。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Exception1. ts
try {
// ...
} catch (error: unknown) {
// 处理异常
}
上面的代码在 TypeScript 中是可以正常运行的,这是因为 TypeScript 支持 any 或 unknown 类型,而 catch 语句中 error 只能声明为 any 或 unknown 类型,但是在 ArkTS 中运行,编译会给你一个大大的错误提示。
因为在 ArkTS 中不支持 any 或 unknown,所以这里应应省略类型标注。因此在 ArkTS 中代码如下所示。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Exception2. ets
try {
// ...
} catch (error) {
// 处理异常
}
类型的别名与变量不能同名
在 TypeScript 中下面的代码是合法的。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Type1. ts
let value: string
type value = number[] // 类型的别名与变量同名
但是在 ArkTS 中不允许这么写。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Type2. ets
let value: string
type ages = number[] // 为避免名称冲突,此处不允许使用 value
类中仅支持一个静态块
在 TypeScript 中可以在类中使用多个静态代码块。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Static1. ts
class Person{
static {
let name = "dhl"
}
static {
let age = 10;
}
}
虽然 TypeScript 支持,但是我还没见过有人会在类中定义多个静态代码块。在 ArkTS 中不允许类中有多个静态块,和 Kotlin 或者 Java 语言对齐的,如果使用多个,编译器会给出错误提示,因此我们需要将多个合并为 1 个。
不支持在 constructor 中声明类字段
在 TypeScript 中可以直接在类的 constructor
中声明类字段,代码如下所示。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Constructor1. ts
class Person {
constructor(
private name: string
) {
this.name = name;
}
getFullName(): string {
return this.name;
}
}
正如你所见,在 constructor
中声明字段 name
,然后在 getFullName()
方法中可以使用 name
,但是在 ArkTS 中不支持在 constructor
中声明类字段,编译器直接会报错。
在 ArkTS 中应该这么写,这和 Kotlin 或者 Java 在类中的使用是一样。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Constructor2. ets
class Person {
private name: string
constructor(name: string) {
this.name = name;
}
getFullName(): string {
return this.name;
}
}
数组必须仅包含可推断类型的元素
在 ArkTS 中,数组中的元素必须是可以根据上下文推断出来的类型,如果类型无法推断出来,则会报错,代码如下所示。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Array1. ts
export const persons: Array<Person> = [
{ "name": "DHL" },
{ "name": "ByteCode" },
]
上面的代码在 TypeScript 中可以正常运行,当看到这段代码有没有觉得很奇怪,创建一个对象,这个对象的元素和类 Person 成员变量一致,就可以往数组中添加,我还是第一次见到代码可以这样写。切换到 ArkTS 会报错,禁止这样写。
在 ArkTS 中正确示例如下所示。
HarmonyPractice/Basic/entry/src/main/ets/syntax/Array2. ets
export const persons: Array<Person> = [
new Person("DHL"),
new Person("ByteCode"),
]
因为篇幅问题,这里我只介绍了运行官方示例项目中遇到的错误,后面我还会分享更多 ArkTs 语法约束。本文所有代码已上传到 github。
感谢你的阅读,写技术文章不易,如果文章对你有帮助,欢迎在看、点赞、分享给身边的朋友,你的点赞是我持续更新的动力
我在 github 上新建了一个 HarmonyPractice 仓库,这个仓库主要用于演示 ArkTS 语法规则、鸿蒙组件的使用,以及鸿蒙实战项目。
本文所有代码已上传到 HarmonyPractice 仓库 Basic 工程中,这个工程主要用于演示 ArkTS 的语法,会第一时间同步鸿蒙新增的语法约束,本文所有的代码均在 Basic 工程中,欢迎点击 HarmonyPractice 仓库右上角 star 以兹鼓励。
HarmonyPractice:https://github.com/hi-dhl/HarmonyPractice
标签:ArkTS,TypeScript,name,鸿蒙,代码,重塑,HarmonyPractice From: https://blog.51cto.com/u_13238266/9582569