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