1# OpenHarmony应用TS&JS编程指南
2
3# 概述
4
5## 目标和适用范围
6
7本指南适用于在OpenHarmony上使用TypeScript和JavaScript进行系统开发或应用开发编写代码的场景。
8
9本文参考业界标准及实践,结合语言引擎技术特点以及OpenHarmony技术特点,为提高代码的规范、安全、性能提供编码建议。
10
11## 规则来源
12
13本指南筛选自OpenHarmony JS通用编程规范[1],结合可发挥OpenHarmony技术特点并且不违反业界认知的规则,包括ESLint、TSC配置等。
14
15ESLint相关规则中的正例反例代码来源于ESLint Rules[2],标注“参见 @typescript-eslint”。
16
17## 章节概览
18
19### [OpenHarmony应用环境限制](#openharmony应用环境限制)
20
21OpenHarmony应用因安全因素的使用限制,均为强制要求。
22
23### 语言特性:[声明与初始化](#声明与初始化)、[数据类型](#数据类型)、[运算与表达式](#运算与表达式)、[函数](#函数)、[类与对象](#类与对象)、[异常](#异常)、[异步](#异步)、[类型](#类型)
24
25## 约定
26
27**规则** :编程时必须遵守的约定
28
29**建议** :编程时必须加以考虑的约定
30
31无论是“规则”还是“建议”,都必须理解该条目这么规定的原因,并努力遵守。
32
33# OpenHarmony应用环境限制
34
35## 使用严格模式
36
37**【级别】规则**
38
39**【描述】**
40
41严格模式(ECMAScript 5开始引入ECMAScript标准中,通过'use strict'语法开启)是采用具有限制性JavaScript变体的一种方式,从而使代码隐式地脱离“马虎模式/稀松模式/懒散模式”(sloppy)。
42
431. 严格模式通过**抛出错误**来消除了一些原有**静默错误** ;
441. 严格模式修复了一些导致JavaScript引擎难以执行优化的缺陷——有时候,相同的代码,严格模式可以比非严格模式下**运行得更快** ;
451. 严格模式**禁用了**在ECMAScript的未来版本中可能会定义的一些语法。
46
47**注:OpenHarmony上方舟编译运行时目前只支持严格模式的TS/JS代码**
48
49## 禁止使用eval()
50
51**【级别】规则**
52
53**【描述】**
54
55使用eval()会让程序比较混乱,导致可读性较差。
56
57**【反例】**
58
59```javascript
60console.log(eval({ a:2 })); // 输出[object Object]
61console.log(eval('"a" + 2')); // 输出'a2'
62console.log(eval('{ a: 2 }')); // 输出2
63console.log(eval('let value = 1 + 1;')); // 输出undefined
64```
65
66## 禁止使用with() {}
67
68**【级别】规则**
69
70**【描述】**
71
72使用with让代码在语义上变得不清晰,因为with的对象,可能会与局部变量产生冲突,从而改变程序原本的用义。
73
74**【反例】**
75
76```javascript
77const foo = { x: 5 };
78with (foo) {
79  let x = 3;
80  console.log(x);  // x = 3
81}
82console.log(foo.x);  // x = 3
83```
84
85## 不要动态创建函数
86
87**【级别】规则**
88
89**【描述】**
90
91定义函数的方法包括3种:函数声明、Function构造函数和函数表达式。不管用哪种方法定义函数,它们都是Function对象的实例,并将继承Function对象所有默认或自定义的方法和属性。以函数构造器创建函数的方式类似于函数eval(),可以接受任何字符串形式作为它的函数体,这就会有安全漏洞的风险。
92
93**【反例】**
94
95```javascript
96let add = new Function('a','b','return a + b');
97// Function构造函数也可以只有一个参数,该参数可以为任意的字符串:
98let dd = new Function('alert("hello")');
99```
100
101**【正例】**
102
103```javascript
104// 函数声明
105function add(a,b){
106  return a+b;
107}
108// 函数表达式
109let add = function(a,b){
110  return a+b;
111}
112```
113
114# 声明与初始化
115
116## 声明变量时要求使用const或let而不是var
117
118**【级别】规则**
119
120**【描述】**
121
122在ECMAScript 6允许开发者使用let和const关键字在块级作用域而非函数作用域下声明变量。块级作用域在很多其他编程语言中很普遍,能帮助开发者避免错误。只读变量用const定义,其它变量用let定义。
123
124**【反例】**
125
126```javascript
127var number = 1;
128var count = 1;
129if (isOK) {
130  count += 1;
131}
132```
133
134**【正例】**
135
136```javascript
137const number = 1;
138let count = 1;
139if (isOK) {
140  count += 1;
141}
142```
143
144# 数据类型
145
146## 不要省略浮点数小数点前后的0
147
148**【级别】规则**
149
150**【描述】**
151
152在JavaScript中,浮点值会包含一个小数点,没有要求小数点之前或之后必须有一个数字。虽然不是一个语法错误,但这种格式的数字使真正的小数和点操作符变的难以区分。由于这个原因,必须在小数点前面和后面有一个数字,以明确表明是要创建一个小数。
153
154**【反例】**
155
156```javascript
157const num = .5;
158const num = 2.;
159const num = -.7;
160```
161
162**【正例】**
163
164```javascript
165const num = 0.5;
166const num = 2.0;
167const num = -0.7;
168```
169
170## 判断变量是否为NaN时必须使用isNaN()方法
171
172**【级别】规则**
173
174**【描述】**
175
176在JavaScript中,NaN是Number类型的一个特殊值。它被用来表示非数值,这里的数值是指在IEEE浮点数算术标准中定义的双精度64位格式的值。
177因为在JavaScript中NaN独特之处在于它不等于任何值,包括它本身,与NaN进行比较的结果是令人困惑:NaN !== NaN or NaN != NaN的值都是true。
178因此,必须使用Number.isNaN()或全局的isNaN()函数来测试一个值是否是NaN。
179
180**【反例】**
181
182```javascript
183if (foo == NaN) {
184  // ...
185}
186if (foo != NaN) {
187  // ...
188}
189```
190
191**【正例】**
192
193```javascript
194if (isNaN(foo)) {
195  // ...
196}
197if (!isNaN(foo)) {
198  // ...
199}
200```
201
202## 浮点型数据判断相等不要直接使用==或===
203
204**【级别】规则**
205
206**【描述】**
207
208由于浮点数在计算机表示中存在精度的问题,数学上相等的数字,经过运算后,其浮点数表示可能不再相等,因而不能使用相等运算符==或===判断浮点数是否相等。
209
210**【反例】**
211
212```javascript
2130.1 + 0.2 == 0.3; // false
2140.1 + 0.2 === 0.3; // false
215```
216
217**【正例】**
218
219```javascript
220const EPSILON = 1e-6;
221const num1 = 0.1;
222const num2 = 0.2;
223const sum = 0.3;
224if(Math.abs(num1 + num2 - sum) < EPSILON) {
225  ...
226}
227```
228
229## 不要在数组上定义或使用非数字属性(length除外)
230
231**【级别】规则**
232
233**【描述】**
234
235在JavaScript中,数组也是对象,可以往数组上添加属性,但为了处理方便和避免出错,数组只应该用来存储有序(即索引连续)的一组数据。必须要添加属性时,考虑用Map或者Object替代。
236
237**【反例】**
238
239```javascript
240const myHash = [];
241myHash['key1'] = 'val1';
242myHash['key2'] = 'val2';
243myHash[0] = '222';
244for (const key in myHash) {
245  // key的值为 0 key1 key2
246  console.log(key);
247}
248console.log(myHash.length); // 数组长度为1
249```
250
251**【正例】**
252
253非数字属性时使用Map、Object
254
255```javascript
256const map = new Map();
257map.set('key1', 'val1');
258map.set('key2', 'val2');
259for(const [key, value] of map) {
260  console.log('属性:' + key + ', 值:' + value);
261}
262```
263
264## 数组遍历优先使用Array对象方法
265
266**【级别】规则**
267
268**【描述】**
269
270对于数组的遍历处理,应该优先使用Array对象方法,如:forEach()、map()、every()、filter()、find()、findIndex()、reduce()、some()。
271注意:不能使用for-in遍历数组。
272
273**【反例】**
274
275```javascript
276const numbers = [1, 2, 3, 4, 5];
277let sum = 0;
278// 使用for in遍历数组
279for (const num in numbers) {
280  console.log(num);
281  sum += num;
282}
283// 依赖已有数组来创建新的数组时,通过for遍历,生成一个新数组
284const increasedByOne = [];
285for (let i = 0; i < numbers.length; i++) {
286  increasedByOne.push(numbers[i] + 1);
287}
288```
289
290**【正例】**
291
292```javascript
293const numbers = [1, 2, 3, 4, 5];
294// 使用for of遍历求和
295let sum = 0;
296for (const num of numbers) {
297  sum += num;
298}
299// 使用forEach遍历求和
300let sum = 0;
301numbers.forEach(num => sum += num);
302// better: 使用reduce方法实现求和,是更好的方式
303const sum = numbers.reduce((total, num) => total + num, 0);
304// 依赖已有数组来创建新的数组,可使用forEach遍历,生成一个新数组
305const increasedByOne = [];
306numbers.forEach(num => increasedByOne.push(num + 1));
307// better: 使用map方法是更好的方式
308const increasedByOne = numbers.map(num => num + 1);
309```
310
311# 运算与表达式
312
313## 判断相等时应使用===和!== ,而不是==和!=
314
315**【级别】规则**
316
317**【描述】**
318
319JavaScript中使用双等==做相等判断时会自动做类型转换,如:[] == false、[] == ![]、3 == '03'都是true,当类型确定时使用全等===做比较可以提高效率。
320
321**【反例】**
322
323```javascript
324age == bee
325foo == true
326bananas != 1
327value == undefined
328typeof foo == 'undefined'
329'hello' != 'world'
3300 == 0
331true == true
332```
333
334**【正例】**
335
336```javascript
337age === bee
338foo === true
339bananas !== 1
340value === undefined
341typeof foo === 'undefined'
342'hello' !== 'world'
3430 === 0
344true === true
345```
346
347**【例外】**
348
349```javascript
350//当判断对象是否是null的时候,可直接使用如下形式:
351obj == null
352obj != null
353```
354
355## 不要在控制性条件表达式中执行赋值操作
356
357**【级别】规则**
358
359**【描述】**
360
361控制性条件表达式常用于if、while、for、?:等条件判断中。
362在控制性条件表达式中执行赋值,常常导致意料之外的行为,且代码的可读性非常差。
363
364**【反例】**
365
366```javascript
367// 在控制性判断中赋值不易理解
368if (isFoo = false) {
369  ...
370}
371```
372
373**【正例】**
374
375```javascript
376const isFoo = someBoolean; // 在上面赋值,if条件判断中直接使用
377if (isFoo) {
378  ...
379}
380```
381
382# 函数
383
384## 必须使用一致的return语句
385
386**【级别】规则**
387
388**【描述】**
389
390不像静态类型语言强制要求函数返回一个指定类型的值,JavaScript允许在一个函数中不同的代码路径返回不同类型的值。
391
392而JavaScript在以下情况下函数会返回undefined:
393
3941. 在退出之前没有执行return语句
3951. 执行return语句,但没有显式地指定一个值
3961. 执行return undefined
3971. 执行return void,其后跟着一个表达式 (例如,一个函数调用)
3981. 执行return,其后跟着其它等于undefined的表达式
399
400在一个函数中,如果任何代码路径显式的返回一个值,但一些代码路径不显式返回一个值,那么这种情况可能是个书写错误,尤其是在一个较大的函数里。因此,函数内,应使用一致的return语句。
401
402**【反例】**
403
404```javascript
405function doSomething(condition) {
406  if (condition) {
407    ...
408    return true;
409  } else {
410    ...
411    return;
412  }
413}
414function doSomething(condition) {
415  if (condition) {
416    ...
417    return true;
418  }
419}
420```
421
422**【正例】**
423
424```javascript
425// 保证所有路径都以相同的方式返回值
426function doSomething(condition) {
427  if (condition) {
428    ...
429    return true;
430  } else {
431    ...
432    return false;
433  }
434}
435
436function doSomething(condition) {
437  if (condition) {
438    ...
439    return true;
440  }
441  ...
442  return false;
443}
444```
445
446## 不要使用arguments,可以选择rest语法替代
447
448**【级别】规则**
449
450**【描述】**
451
452rest参数是一个真正的数组,也就是说能够在它上面直接使用所有的数组方法,比如sort,map,forEach或pop,而arguments是一个类数组。因此,应选择使用rest语法替代arguments。另外,rest参数必须是列表中的最后一个参数。
453
454**【反例】**
455
456```javascript
457function concatenateAll() {
458  // 因为arguments是类数组,不能直接使用join方法,需要先转换为真正的数组
459  const args = Array.prototype.slice.call(arguments);
460  return args.join('');
461}
462```
463
464**【正例】**
465
466```javascript
467function concatenateAll(...args) {
468  return args.join('');
469}
470```
471
472## 不要将This赋值给一个变量,约束This在一个Scope内使用
473
474**【级别】规则**
475
476**【描述】**
477
478箭头函数提供了更简洁的语法,并且箭头函数中的this对象指向是不变的,this绑定到定义时所在的对象,有更好的代码可读性。而保存this引用的方式,容易让开发人员搞混。
479
480**【反例】**
481
482```javascript
483function foo() {
484  const self = this;
485  return function() {
486    console.log(self);
487  };
488}
489```
490
491**【正例】**
492
493```javascript
494function foo() {
495  return () => {
496    console.log(this);
497  };
498}
499```
500
501参见:[@typescript-eslint/no-this-alias](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-this-alias.md)
502
503ESLint的描述更加严苛,我们认为this不应该在任何情况下赋值给一个变量。
504
505# 类与对象
506
507## 使用点号来访问对象的属性,只有计算属性使用[]
508
509**【级别】规则**
510
511**【描述】**
512
513在JavaScript中,可以使用点号 (foo.bar) 或者方括号 (foo['bar'])来访问属性。然而,点号通常是首选,因为它更加易读,简洁,也更适于JavaScript压缩。
514
515**【正例】**
516
517```javascript
518const name = obj.name;
519const key = getKeyFromDB();
520const prop = obj[key]; // 属性名是变量时才使用[]
521```
522
523## 不要修改内置对象的原型,或向原型添加方法
524
525**【级别】规则**
526
527**【描述】**
528
529内置对象作为一套公共接口,具有约定俗成的行为方式,若修改其原型,可能破坏接口语义。因此,永远不要修改内置对象的原型,或向原型添加方法。
530
531**【反例】**
532
533```javascript
534Array.prototype.indexOf = function () {
535  return -1;
536}
537// 其它地方使用的时候
538const arr = [1, 1, 1, 1, 1, 2, 1, 1, 1];
539console.log(arr.indexOf(2)); // 输出-1
540```
541
542## 不要删除对象的可计算属性
543
544**【级别】规则**
545
546**【描述】**
547
548delete会改变对象的布局,而delete对象的可计算属性会非常危险,而且会大幅约束语言运行时的优化从而影响执行性能。
549
550注意:建议不删除对象的任何属性,如果有需要,建议用map和set。
551
552**【反例】**
553
554```javascript
555// Can be replaced with the constant equivalents, such as container.aaa
556delete container['aaa'];
557
558// Dynamic, difficult-to-reason-about lookups
559const name = 'name';
560delete container[name];
561delete container[name.toUpperCase()];
562```
563
564**【正例】**
565
566```javascript
567// 一定程度也会影响优化性能,但比删除可计算属性好一些。
568delete container.aaa;
569
570delete container[7];
571```
572
573参见:[@typescript-eslint/no-dynamic-delete](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-dynamic-delete.md)
574
575# 异常
576
577## 不要使用return、break、continue或抛出异常使finally块非正常结束
578
579**【级别】规则**
580
581**【描述】**
582
583在finally代码块中,直接使用return、break、continue、throw语句,或由于调用方法的异常未处理,会导致finally代码块无法正常结束。非正常结束的finally代码块会影响try或catch代码块中异常的抛出,也可能会影响方法的返回值。所以要保证finally代码块正常结束。
584
585**【反例】**
586
587```javascript
588function foo() {
589  try {
590    ...
591    return 1;
592  } catch(err) {
593    ...
594    return 2;
595  } finally {
596    return 3;
597 }
598}
599```
600
601**【正例】**
602
603```javascript
604function foo() {
605  try {
606    ...
607    return 1;
608  } catch(err) {
609    ...
610    return 2;
611  } finally {
612    console.log('XXX!');
613  }
614}
615```
616
617# 异步
618
619## 禁用不必要的return await
620
621**【级别】规则**
622
623**【描述】**
624
625因为async function的返回值总是封装在Promise.resolve,return await实际上并没有做任何事情,只是在Promise resolve或reject之前增加了额外的时间。唯一有效的情况是,在try/catch语句中使用return await来捕获另一个基于Promise的函数的错误。
626
627**【反例】**
628
629```javascript
630async function foo() {
631  return await bar();
632}
633```
634
635**【正例】**
636
637```javascript
638async function foo() {
639  return bar();
640}
641async function foo() {
642  await bar();
643  return;
644}
645async function foo() {
646  const baz = await bar();
647  return baz;
648}
649async function foo() {
650  try {
651    return await bar();
652  } catch (error) {
653    // here can be executed, go on
654  }
655}
656```
657
658## 不允许等待非Thenable的值
659
660**【级别】规则**
661
662**【描述】**
663
664如果await一个非Thenable的值,await会把该值转换为已正常处理的Promise,然后等待其处理结果。此时await反而会影响代码性能。
665
666**【反例】**
667
668```javascript
669async function f3() {
670  const y = await 20;
671  console.log(y); // 20
672}
673
674f3();
675console.log(30);
676
677// output
678// 30
679// 20
680```
681
682**【正例】**
683
684```javascript
685async function f3() {
686  const y = 20;
687  console.log(y); // 20
688}
689
690f3();
691console.log(30);
692
693// output
694// 20
695// 30
696```
697
698参见:[@typescript-eslint/await-thenable](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/await-thenable.md)
699
700# 类型
701
702## 强制将Null和Undefined作为独立类型标注
703
704**【级别】规则**
705
706**【描述】**
707
708Null和Undefined作为独立类型标注,可以提高代码的安全性,避免空指针异常。
709
710**【反例】**
711
712```javascript
713let userName: string;
714userName = 'hello';
715userName = undefined;
716```
717
718**【正例】**
719
720```javascript
721let userName: string | undefined;
722userName = 'hello';
723userName = undefined;
724```
725
726## 必须显式声明函数及类方法的返回值类型
727
728**【级别】规则**
729
730**【描述】**
731
732显式声明返回类型,这可确保返回值被分配给正确类型的变量;或者在没有返回值的情况下,调用代码不会尝试把undefined分配给变量。
733
734**【反例】**
735
736```javascript
737// 没有返回值时,没有声明返回值类型为void
738function test() {
739  return;
740}
741// 没有声明返回值类型为number
742function fn() {
743  return 1;
744};
745// 没有声明返回值类型为string
746let arrowFn = () => 'test';
747class Test {
748  // 没有返回值时,没有声明返回值类型为void
749  method() {
750    return;
751  }
752}
753```
754
755**【正例】**
756
757```javascript
758// 函数没有返回值时,显式声明返回值类型为void
759function test(): void {
760  return;
761}
762// 显式声明返回值类型为number
763function fn(): number {
764  return 1;
765};
766// 显式声明返回值类型为 string
767let arrowFn = (): string => 'test';
768class Test {
769  // 没有返回值时,显式声明返回值类型为void
770  method(): void {
771    return;
772  }
773}
774```
775
776参见:[@typescript-eslint/explicit-function-return-type](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/explicit-function-return-type.md)
777
778## 强制使用类型导出的一致性
779
780**【级别】规则**
781
782**【描述】**
783
784如果导出类型(type),将导出类型和导出其他对象分开写。
785
786**【反例】**
787
788```javascript
789interface ButtonProps {
790  onClick: () => void;
791}
792class Button implements ButtonProps {
793  onClick() {
794    console.log('button!');
795  }
796}
797export { Button, ButtonProps };
798```
799
800**【正例】**
801
802```javascript
803interface ButtonProps {
804  onClick: () => void;
805}
806class Button implements ButtonProps {
807  onClick() {
808    console.log('button!');
809  }
810}
811export { Button };
812export type { ButtonProps };
813```
814
815参见:[@typescript-eslint/consistent-type-exports](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/consistent-type-exports.md)
816
817## 强制使用类型导入的一致性
818
819**【级别】规则**
820
821**【描述】**
822
823如果导入类型(type),将导入类型和导入其他对象分开写。
824
825**【反例】**
826
827```javascript
828import { Foo } from 'Foo';
829import Bar from 'Bar';
830type T = Foo;
831const x: Bar = 1;
832```
833
834**【正例】**
835
836```javascript
837import type { Foo } from 'Foo';
838import type Bar from 'Bar';
839type T = Foo;
840const x: Bar = 1;
841```
842
843参见:[@typescript-eslint/consistent-type-imports](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/consistent-type-imports.md)
844
845## 避免使用any
846
847**【级别】规则**
848
849**【描述】**
850
851使用了`any`类型会使所有编译时的类型检查被忽略。一般来说,这个行为不是必需的,也不符合期望。如果类型未知,要求使用`unknown` 。
852当引入的三方件不是使用TS语言或者没有提供TS类型声明时,可以使用`any`来声明相关的三方件对象。
853
854## 不允许定义any类型
855
856**【级别】规则**
857
858**【描述】**
859
860不允许定义any类型。它的目的是为了让类型在TS中尽量明确,帮助语言运行时优化。
861
862**【反例】**
863
864```javascript
865const age: any = 'seventeen';
866function greet(): any {}
867function greet(param: Array<any>): string {}
868```
869
870**【正例】**
871
872```javascript
873const age: number = 17;
874function greet(): string {}
875function greet(param: Array<string>): string {}
876```
877
878参见:[@typescript-eslint/no-explicit-any](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-explicit-any.md)
879
880## 不允许使用any作为参数传递
881
882**【级别】规则**
883
884**【反例】**
885
886```javascript
887declare function foo(arg1: string, arg2: number, arg3: string): void;
888
889const anyTyped = 1 as any;
890
891foo(...anyTyped);
892foo(anyTyped, 1, 'a');
893
894const tuple1 = ['a', anyTyped, 'b'] as const;
895foo(...tuple1);
896```
897
898**【正例】**
899
900```javascript
901declare function foo(arg1: string, arg2: number, arg3: string): void;
902
903foo('a', 1, 'b');
904
905const tuple1 = ['a', 1, 'b'] as const;
906foo(...tuple1);
907```
908
909参见:[@typescript-eslint/no-unsafe-argument](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unsafe-argument.md)
910
911## 不允许在赋值中使用any
912
913**【级别】规则**
914
915**【反例】**
916
917```javascript
918const x = 1 as any,
919
920const x: Set<string> = new Set<any>();
921```
922
923**【正例】**
924
925```javascript
926const x = 1;
927
928const x: Set<string> = new Set<string>();
929```
930
931参见:[@typescript-eslint/no-unsafe-assignment](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md)
932
933## 不允许call类型为any的变量
934
935**【级别】规则**
936
937**【反例】**
938
939```javascript
940declare const anyVar: any;
941declare const nestedAny: { prop: any };
942
943anyVar();
944anyVar.a.b();
945
946nestedAny.prop();
947nestedAny.prop['a']();
948```
949
950**【正例】**
951
952```javascript
953declare const typedVar: () => void;
954declare const typedNested: { prop: { a: () => void } };
955
956typedVar();
957typedNested.prop.a();
958```
959
960参见:[@typescript-eslint/no-unsafe-call](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unsafe-call.md)
961
962## 不允许访问类型为any的对象的成员
963
964**【级别】规则**
965
966**【反例】**
967
968```markup
969declare const anyVar: any;
970declare const nestedAny: { prop: any };
971
972anyVar.a;
973anyVar.a.b;
974
975nestedAny.prop.a;
976nestedAny.prop['a'];
977```
978
979**【正例】**
980
981```javascript
982declare const properlyTyped: { prop: { a: string } };
983
984properlyTyped.prop.a;
985properlyTyped.prop['a'];
986```
987
988参见:[@typescript-eslint/no-unsafe-member-access](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md)
989
990## 不允许声明函数返回值类型为any或者any[]
991
992**【级别】规则**
993
994**【反例】**
995
996```javascript
997function foo1() {
998  return 1 as any;
999}
1000```
1001
1002**【正例】**
1003
1004```javascript
1005function foo1() : number {
1006  return 1;
1007}
1008```
1009
1010参见:[@typescript-eslint/no-unsafe-return](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/no-unsafe-return.md)
1011
1012# 参考
1013
10141. 《OpenHarmony JS通用编程规范》:[https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/OpenHarmony-JavaScript-coding-style-guide.md](https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/OpenHarmony-JavaScript-coding-style-guide.md)
10151. ESLint Rules:[https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin/docs/rules](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin/docs/rules)
10161. 《高性能JavaScript》
1017