文档管理中心

您当前浏览的HarmonyOS 5.0.0(API 12)文档归档不再维护,推荐您使用最新版本。详细请参考文档维护策略变更

指南基础入门学习ArkTS语言从TypeScript到ArkTS的适配指导适配指导案例

适配指导案例

本文导读
展开章节

本文通过更多应用场景中的案例,提供在ArkTS语法规则下将TS代码适配成ArkTS代码的建议。各章以ArkTS语法规则英文名称命名,每个案例提供适配前的TS代码和适配后的ArkTS代码。

arkts-identifiers-as-prop-names

应用代码

收起
自动换行
深色代码主题
复制
  1. interface W {
  2. bundleName: string
  3. action: string
  4. entities: string[]
  5. }
  6. let wantInfo: W = {
  7. 'bundleName': 'com.huawei.hmos.browser',
  8. 'action': 'ohos.want.action.viewData',
  9. 'entities': ['entity.system.browsable']
  10. }

建议改法

收起
自动换行
深色代码主题
复制
  1. interface W {
  2. bundleName: string
  3. action: string
  4. entities: string[]
  5. }
  6. let wantInfo: W = {
  7. bundleName: 'com.huawei.hmos.browser',
  8. action: 'ohos.want.action.viewData',
  9. entities: ['entity.system.browsable']
  10. }

arkts-no-any-unknown

按照业务逻辑,将代码中的any, unknown改为具体的类型

收起
自动换行
深色代码主题
复制
  1. function printObj(obj: any) {
  2. console.log(obj);
  3. }
  4. printObj('abc');

建议改法

收起
自动换行
深色代码主题
复制
  1. function printObj(obj: string) {
  2. console.log(obj);
  3. }
  4. printObj('abc');

标注JSON.parse返回值类型

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. v: number = 0
  3. s: string = ''
  4. foo(str: string) {
  5. let tmpStr = JSON.parse(str);
  6. if (tmpStr.add != undefined) {
  7. this.v = tmpStr.v;
  8. this.s = tmpStr.s;
  9. }
  10. }
  11. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class A {
  2. v: number = 0
  3. s: string = ''
  4. foo(str: string) {
  5. let tmpStr: Record<string, Object> = JSON.parse(str);
  6. if (tmpStr.add != undefined) {
  7. this.v = tmpStr.v as number;
  8. this.s = tmpStr.s as string;
  9. }
  10. }
  11. }

使用Record类型

应用代码

收起
自动换行
深色代码主题
复制
  1. function printProperties(obj: any) {
  2. console.log(obj.name);
  3. console.log(obj.value);
  4. }

建议改法

收起
自动换行
深色代码主题
复制
  1. function printProperties(obj: Record<string, Object>) {
  2. console.log(obj.name as string);
  3. console.log(obj.value as string);
  4. }

arkts-no-call-signature

使用函数类型来替代。

应用代码

收起
自动换行
深色代码主题
复制
  1. interface I {
  2. (value: string): void;
  3. }
  4. function foo(fn: I) {
  5. fn('abc');
  6. }
  7. foo((value: string) => {
  8. console.log(value);
  9. })

建议改法

收起
自动换行
深色代码主题
复制
  1. type I = (value: string) => void
  2. function foo(fn: I) {
  3. fn('abc');
  4. }
  5. foo((value: string) => {
  6. console.log(value);
  7. })

arkts-no-ctor-signatures-type

应用代码

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. type ControllerConstructor = {
  8. new (value: string): Controller;
  9. }
  10. class Menu {
  11. controller: ControllerConstructor = Controller
  12. createController() {
  13. if (this.controller) {
  14. return new this.controller(123);
  15. }
  16. return null;
  17. }
  18. }
  19. let t = new Menu();
  20. console.log(t.createController()!.value);

建议改法

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. type ControllerConstructor = () => Controller;
  8. class Menu {
  9. controller: ControllerConstructor = () => {
  10. return new Controller('abc');
  11. }
  12. createController() {
  13. if (this.controller) {
  14. return this.controller();
  15. }
  16. return null;
  17. }
  18. }
  19. let t: Menu = new Menu();
  20. console.log(t.createController()!.value);

arkts-no-indexed-signatures

使用Record类型来替代。

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo(data: { [key: string]: string }) {
  2. data['a'] = 'a';
  3. data['b'] = 'b';
  4. data['c'] = 'c';
  5. }

建议改法

收起
自动换行
深色代码主题
复制
  1. function foo(data: Record<string, string>) {
  2. data['a'] = 'a';
  3. data['b'] = 'b';
  4. data['c'] = 'c';
  5. }

arkts-no-typing-with-this

应用代码

收起
自动换行
深色代码主题
复制
  1. class C {
  2. getInstance(): this {
  3. return this;
  4. }
  5. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class C {
  2. getInstance(): C {
  3. return this;
  4. }
  5. }

arkts-no-ctor-prop-decls

应用代码

收起
自动换行
深色代码主题
复制
  1. class Person {
  2. constructor(readonly name: string) {}
  3. getName(): string {
  4. return this.name;
  5. }
  6. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class Person {
  2. name: string
  3. constructor(name: string) {
  4. this.name = name;
  5. }
  6. getName(): string {
  7. return this.name;
  8. }
  9. }

arkts-no-ctor-signatures-iface

应用代码

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. interface ControllerConstructor {
  8. new (value: string): Controller;
  9. }
  10. class Menu {
  11. controller: ControllerConstructor = Controller
  12. createController() {
  13. if (this.controller) {
  14. return new this.controller('abc');
  15. }
  16. return null;
  17. }
  18. }
  19. let t = new Menu();
  20. console.log(t.createController()!.value);

建议改法

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. type ControllerConstructor = () => Controller;
  8. class Menu {
  9. controller: ControllerConstructor = () => {
  10. return new Controller('abc');
  11. }
  12. createController() {
  13. if (this.controller) {
  14. return this.controller();
  15. }
  16. return null;
  17. }
  18. }
  19. let t: Menu = new Menu();
  20. console.log(t.createController()!.value);

arkts-no-props-by-index

可以转换成Record类型,用来访问对象的属性。

应用代码

收起
自动换行
深色代码主题
复制
  1. import { router } from '@kit.ArkUI';
  2. let params: Object = router.getParams();
  3. let funNum: number = params['funNum'];
  4. let target: string = params['target'];

建议改法

收起
自动换行
深色代码主题
复制
  1. import { router } from '@kit.ArkUI';
  2. let params = router.getParams() as Record<string, string | number>;
  3. let funNum: number = params.funNum as number;
  4. let target: string = params.target as string;

arkts-no-inferred-generic-params

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. str: string = ''
  3. }
  4. class B extends A {}
  5. class C extends A {}
  6. let arr: Array<A> = [];
  7. let originMenusMap:Map<string, C> = new Map(arr.map(item => [item.str, (item instanceof C) ? item: null]));

建议改法

收起
自动换行
深色代码主题
复制
  1. class A {
  2. str: string = ''
  3. }
  4. class B extends A {}
  5. class C extends A {}
  6. let arr: Array<A> = [];
  7. let originMenusMap: Map<string, C | null> = new Map<string, C | null>(arr.map<[string, C | null]>(item => [item.str, (item instanceof C) ? item: null]));

原因

(item instanceof C) ? item: null 需要声明类型为C | null,由于编译器无法推导出map的泛型类型参数,需要显式标注。

arkts-no-regexp-literals

应用代码

收起
自动换行
深色代码主题
复制
  1. let regex: RegExp = /\s*/g;

建议改法

收起
自动换行
深色代码主题
复制
  1. let regexp: RegExp = new RegExp('\\s*','g');

原因

如果正则表达式中使用了标志符,需要将其作为new RegExp()的参数。

arkts-no-untyped-obj-literals

从SDK中导入类型,标注object literal类型

应用代码

收起
自动换行
深色代码主题
复制
  1. const area = {
  2. pixels: new ArrayBuffer(8),
  3. offset: 0,
  4. stride: 8,
  5. region: { size: { height: 1,width:2 }, x: 0, y: 0 }
  6. }

建议改法

收起
自动换行
深色代码主题
复制
  1. import { image } from '@kit.ImageKit';
  2. const area: image.PositionArea = {
  3. pixels: new ArrayBuffer(8),
  4. offset: 0,
  5. stride: 8,
  6. region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
  7. }

用class为object literal标注类型,需要class的构造函数无参数

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: number = 1
  3. constructor(value: number) {
  4. this.value = value;
  5. }
  6. }
  7. let t: Test = { value: 2 };

建议改法1

收起
自动换行
深色代码主题
复制
  1. // 去除构造函数
  2. class Test {
  3. value: number = 1
  4. }
  5. let t: Test = { value: 2 };

建议改法2

收起
自动换行
深色代码主题
复制
  1. // 使用new
  2. class Test {
  3. value: number = 1
  4. constructor(value: number) {
  5. this.value = value;
  6. }
  7. }
  8. let t: Test = new Test(2);

原因

收起
自动换行
深色代码主题
复制
  1. class C {
  2. value: number = 1
  3. constructor(n: number) {
  4. if (n < 0) {
  5. throw new Error('Negative');
  6. }
  7. this.value = n;
  8. }
  9. }
  10. let s: C = new C(-2); //抛出异常
  11. let t: C = { value: -2 }; //ArkTS不支持

例如在上面的例子中,如果允许使用C来标注object literal的类型,那么上述代码中的变量t会导致行为的二义性。ArkTS禁止通过object literal来绕过这一行为。

用class/interface为object literal标注类型,需要使用identifier作为object literal的key

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: number = 0
  3. }
  4. let arr: Test[] = [
  5. {
  6. 'value': 1
  7. },
  8. {
  9. 'value': 2
  10. },
  11. {
  12. 'value': 3
  13. }
  14. ]

建议改法

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: number = 0
  3. }
  4. let arr: Test[] = [
  5. {
  6. value: 1
  7. },
  8. {
  9. value: 2
  10. },
  11. {
  12. value: 3
  13. }
  14. ]

使用Record为object literal标注类型,需要使用字符串作为object literal的key

应用代码

收起
自动换行
深色代码主题
复制
  1. let obj: Record<string, number | string> = {
  2. value: 123,
  3. name: 'abc'
  4. }

建议改法

收起
自动换行
深色代码主题
复制
  1. let obj: Record<string, number | string> = {
  2. 'value': 123,
  3. 'name': 'abc'
  4. }

函数参数类型包含index signature

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo(obj: { [key: string]: string}): string {
  2. if (obj != undefined && obj != null) {
  3. return obj.value1 + obj.value2;
  4. }
  5. return '';
  6. }

建议改法

收起
自动换行
深色代码主题
复制
  1. function foo(obj: Record<string, string>): string {
  2. if (obj != undefined && obj != null) {
  3. return obj.value1 + obj.value2;
  4. }
  5. return '';
  6. }

函数实参使用了object literal

应用代码

收起
自动换行
深色代码主题
复制
  1. (fn) => {
  2. fn({ value: 123, name:'' });
  3. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class T {
  2. value: number = 0
  3. name: string = ''
  4. }
  5. (fn: (v: T) => void) => {
  6. fn({ value: 123, name: '' });
  7. }

class/interface 中包含方法

应用代码

收起
自动换行
深色代码主题
复制
  1. interface T {
  2. foo(value: number): number
  3. }
  4. let t:T = { foo: (value) => { return value } };

建议改法1

收起
自动换行
深色代码主题
复制
  1. interface T {
  2. foo: (value: number) => number
  3. }
  4. let t:T = { foo: (value) => { return value } };

建议改法2

收起
自动换行
深色代码主题
复制
  1. class T {
  2. foo: (value: number) => number = (value: number) => {
  3. return value;
  4. }
  5. }
  6. let t:T = new T();

原因

class/interface中声明的方法应该被所有class的实例共享。ArkTS不支持通过object literal改写实例方法。ArkTS支持函数类型的属性。

export default对象

应用代码

收起
自动换行
深色代码主题
复制
  1. export default {
  2. onCreate() {
  3. // ...
  4. },
  5. onDestroy() {
  6. // ...
  7. }
  8. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. onCreate() {
  3. // ...
  4. }
  5. onDestroy() {
  6. // ...
  7. }
  8. }
  9. export default new Test()

通过导入namespace获取类型

应用代码

收起
自动换行
深色代码主题
复制
  1. // test.d.ets
  2. declare namespace test {
  3. interface I {
  4. id: string;
  5. type: number;
  6. }
  7. function foo(name: string, option: I): void;
  8. }
  9. export default test;
  10. // app.ets
  11. import { test } from 'test';
  12. let option = { id: '', type: 0 };
  13. test.foo('', option);

建议改法

收起
自动换行
深色代码主题
复制
  1. // test.d.ets
  2. declare namespace test {
  3. interface I {
  4. id: string;
  5. type: number;
  6. }
  7. function foo(name: string, option: I): void;
  8. }
  9. export default test;
  10. // app.ets
  11. import { test } from 'test';
  12. let option: test.I = { id: '', type: 0 };
  13. test.foo('', option);

原因

对象字面量缺少类型,根据test.foo分析可以得知,option的类型来源于声明文件,那么只需要将类型导入即可。

注意到在test.d.ets中,I是定义在namespace中的,所以在ets文件中,先导入namespace,再通过名称获取相应的类型。

object literal传参给Object类型

应用代码

收起
自动换行
深色代码主题
复制
  1. function emit(event: string, ...args: Object[]): void {}
  2. emit('', {
  3. 'action': 11,
  4. 'outers': false
  5. });

建议改法

收起
自动换行
深色代码主题
复制
  1. function emit(event: string, ...args: Object[]): void {}
  2. let emitArg: Record<string, number | boolean> = {
  3. 'action': 11,
  4. 'outers': false
  5. }
  6. emit('', emitArg);

arkts-no-obj-literals-as-types

应用代码

收起
自动换行
深色代码主题
复制
  1. type Person = { name: string, age: number }

建议改法

收起
自动换行
深色代码主题
复制
  1. interface Person {
  2. name: string,
  3. age: number
  4. }

arkts-no-noninferrable-arr-literals

应用代码

收起
自动换行
深色代码主题
复制
  1. let permissionList = [
  2. { name: '设备信息', value: '用于分析设备的续航、通话、上网、SIM卡故障等' },
  3. { name: '麦克风', value: '用于反馈问题单时增加语音' },
  4. { name: '存储', value: '用于反馈问题单时增加本地文件附件' }
  5. ]

建议改法

为对象字面量声明类型

收起
自动换行
深色代码主题
复制
  1. class PermissionItem {
  2. name?: string
  3. value?: string
  4. }
  5. let permissionList: PermissionItem[] = [
  6. { name: '设备信息', value: '用于分析设备的续航、通话、上网、SIM卡故障等' },
  7. { name: '麦克风', value: '用于反馈问题单时增加语音' },
  8. { name: '存储', value: '用于反馈问题单时增加本地文件附件' }
  9. ]

arkts-no-method-reassignment

应用代码

收起
自动换行
深色代码主题
复制
  1. class C {
  2. add(left: number, right: number): number {
  3. return left + right;
  4. }
  5. }
  6. function sub(left: number, right: number): number {
  7. return left - right;
  8. }
  9. let c1 = new C();
  10. c1.add = sub;

建议改法

收起
自动换行
深色代码主题
复制
  1. class C {
  2. add: (left: number, right: number) => number =
  3. (left: number, right: number) => {
  4. return left + right;
  5. }
  6. }
  7. function sub(left: number, right: number): number {
  8. return left - right;
  9. }
  10. let c1 = new C();
  11. c1.add = sub;

arkts-no-polymorphic-unops

应用代码

收起
自动换行
深色代码主题
复制
  1. let a = +'5';
  2. let b = -'5';
  3. let c = ~'5';
  4. let d = +'string';

建议改法

收起
自动换行
深色代码主题
复制
  1. let a = Number.parseInt('5');
  2. let b = -Number.parseInt('5');
  3. let c = ~Number.parseInt('5');
  4. let d = new Number('string');

arkts-no-type-query

应用代码

收起
自动换行
深色代码主题
复制
  1. // module1.ts
  2. class C {
  3. value: number = 0
  4. }
  5. export let c = new C()
  6. // module2.ts
  7. import { c } from './module1'
  8. let t: typeof c = { value: 123 };

建议改法

收起
自动换行
深色代码主题
复制
  1. // module1.ts
  2. class C {
  3. value: number = 0
  4. }
  5. export { C }
  6. // module2.ts
  7. import { C } from './module1'
  8. let t: C = { value: 123 };

arkts-no-in

使用Object.keys判断属性是否存在

应用代码

收起
自动换行
深色代码主题
复制
  1. function test(str: string, obj: Record<string, Object>) {
  2. return str in obj;
  3. }

建议改法

收起
自动换行
深色代码主题
复制
  1. function test(str: string, obj: Record<string, Object>) {
  2. for (let i of Object.keys(obj)) {
  3. if (i == str) {
  4. return true;
  5. }
  6. }
  7. return false;
  8. }

arkts-no-destruct-assignment

应用代码

收起
自动换行
深色代码主题
复制
  1. let map = new Map<string, string>([['a', 'a'], ['b', 'b']]);
  2. for (let [key, value] of map) {
  3. console.log(key);
  4. console.log(value);
  5. }

建议改法

使用数组

收起
自动换行
深色代码主题
复制
  1. let map = new Map<string, string>([['a', 'a'], ['b', 'b']]);
  2. for (let arr of map) {
  3. let key = arr[0];
  4. let value = arr[1];
  5. console.log(key);
  6. console.log(value);
  7. }

arkts-no-types-in-catch

应用代码

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit'
  2. try {
  3. // ...
  4. } catch (e: BusinessError) {
  5. console.error(e.message, e.code);
  6. }

建议改法

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit'
  2. try {
  3. // ...
  4. } catch (error) {
  5. let e: BusinessError = error as BusinessError;
  6. console.error(e.message, e.code);
  7. }

arkts-no-for-in

应用代码

收起
自动换行
深色代码主题
复制
  1. interface Person {
  2. [name: string]: string
  3. }
  4. let p: Person = {
  5. name: 'tom',
  6. age: '18'
  7. };
  8. for (let t in p) {
  9. console.log(p[t]); // log: "tom", "18"
  10. }

建议改法

收起
自动换行
深色代码主题
复制
  1. let p: Record<string, string> = {
  2. 'name': 'tom',
  3. 'age': '18'
  4. };
  5. for (let ele of Object.entries(p)) {
  6. console.log(ele[1]); // log: "tom", "18"
  7. }

arkts-no-mapped-types

应用代码

收起
自动换行
深色代码主题
复制
  1. class C {
  2. a: number = 0
  3. b: number = 0
  4. c: number = 0
  5. }
  6. type OptionsFlags = {
  7. [Property in keyof C]: string
  8. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class C {
  2. a: number = 0
  3. b: number = 0
  4. c: number = 0
  5. }
  6. type OptionsFlags = Record<keyof C, string>

arkts-limited-throw

应用代码

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit'
  2. function ThrowError(error: BusinessError) {
  3. throw error;
  4. }

建议改法

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit'
  2. function ThrowError(error: BusinessError) {
  3. throw error as Error;
  4. }

原因

throw语句中值的类型必须为Error或者其继承类,如果继承类是一个泛型,会有编译期报错。建议使用as将类型转换为Error。

arkts-no-standalone-this

函数内使用this

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo() {
  2. console.log(this.value);
  3. }
  4. let obj = { value: 'abc' };
  5. foo.apply(obj);

建议改法1

使用类的方法实现,如果该方法被多个类使用,可以考虑采用继承的机制

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: string = ''
  3. constructor (value: string) {
  4. this.value = value
  5. }
  6. foo() {
  7. console.log(this.value);
  8. }
  9. }
  10. let obj: Test = new Test('abc');
  11. obj.foo();

建议改法2

将this作为参数传入

收起
自动换行
深色代码主题
复制
  1. function foo(obj: Test) {
  2. console.log(obj.value);
  3. }
  4. class Test {
  5. value: string = ''
  6. }
  7. let obj: Test = { value: 'abc' };
  8. foo(obj);

建议改法3

将属性作为参数传入

收起
自动换行
深色代码主题
复制
  1. function foo(value: string) {
  2. console.log(value);
  3. }
  4. class Test {
  5. value: string = ''
  6. }
  7. let obj: Test = { value: 'abc' };
  8. foo(obj.value);

class的静态方法内使用this

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. static value: number = 123
  3. static foo(): number {
  4. return this.value
  5. }
  6. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. static value: number = 123
  3. static foo(): number {
  4. return Test.value
  5. }
  6. }

arkts-no-spread

应用代码

收起
自动换行
深色代码主题
复制
  1. // test.d.ets
  2. declare namespace test {
  3. interface I {
  4. id: string;
  5. type: number;
  6. }
  7. function foo(): I;
  8. }
  9. export default test
  10. // app.ets
  11. import test from 'test';
  12. let t: test.I = {
  13. ...test.foo(),
  14. type: 0
  15. }

建议改法

收起
自动换行
深色代码主题
复制
  1. // test.d.ets
  2. declare namespace test {
  3. interface I {
  4. id: string;
  5. type: number;
  6. }
  7. function foo(): I;
  8. }
  9. export default test
  10. // app.ets
  11. import test from 'test';
  12. let t: test.I = test.foo();
  13. t.type = 0;

原因

ArkTS中,对象布局在编译期是确定的。如果需要将一个对象的所有属性展开赋值给另一个对象可以通过逐个属性赋值语句完成。在本例中,需要展开的对象和赋值的目标对象类型恰好相同,可以通过改变该对象属性的方式重构代码。

arkts-no-ctor-signatures-funcs

在class内声明属性,而不是在构造函数上。

应用代码

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value
  5. }
  6. }
  7. type ControllerConstructor = new (value: string) => Controller;
  8. class Menu {
  9. controller: ControllerConstructor = Controller
  10. createController() {
  11. if (this.controller) {
  12. return new this.controller('abc');
  13. }
  14. return null;
  15. }
  16. }
  17. let t = new Menu()
  18. console.log(t.createController()!.value)

建议改法

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. type ControllerConstructor = () => Controller;
  8. class Menu {
  9. controller: ControllerConstructor = () => { return new Controller('abc') }
  10. createController() {
  11. if (this.controller) {
  12. return this.controller();
  13. }
  14. return null;
  15. }
  16. }
  17. let t: Menu = new Menu();
  18. console.log(t.createController()!.value);

arkts-no-globalthis

由于无法为globalThis添加静态类型,只能通过查找的方式访问globalThis的属性,造成额外的性能开销。另外,无法为globalThis的属性标记类型,无法保证对这些属性操作的安全和高性能。因此ArkTS不支持globalThis。

  1. 建议按照业务逻辑根据import/export语法实现数据在不同模块的传递。

  2. 必要情况下,可以通过构造的单例对象来实现全局对象的功能。(说明: 不能在har中定义单例对象,har在打包时会在不同的hap中打包两份,无法实现单例。)

构造单例对象

收起
自动换行
深色代码主题
复制
  1. // 构造单例对象
  2. export class GlobalContext {
  3. private constructor() {}
  4. private static instance: GlobalContext;
  5. private _objects = new Map<string, Object>();
  6. public static getContext(): GlobalContext {
  7. if (!GlobalContext.instance) {
  8. GlobalContext.instance = new GlobalContext();
  9. }
  10. return GlobalContext.instance;
  11. }
  12. getObject(value: string): Object | undefined {
  13. return this._objects.get(value);
  14. }
  15. setObject(key: string, objectClass: Object): void {
  16. this._objects.set(key, objectClass);
  17. }
  18. }

应用代码

收起
自动换行
深色代码主题
复制
  1. // file1.ts
  2. export class Test {
  3. value: string = '';
  4. foo(): void {
  5. globalThis.value = this.value;
  6. }
  7. }
  8. // file2.ts
  9. globalThis.value;

建议改法

收起
自动换行
深色代码主题
复制
  1. // file1.ts
  2. import { GlobalContext } from '../GlobalContext'
  3. export class Test {
  4. value: string = '';
  5. foo(): void {
  6. GlobalContext.getContext().setObject('value', this.value);
  7. }
  8. }
  9. // file2.ts
  10. import { GlobalContext } from '../GlobalContext'
  11. GlobalContext.getContext().getObject('value');

arkts-no-func-apply-bind-call

使用标准库中接口

应用代码

收起
自动换行
深色代码主题
复制
  1. let arr: number[] = [1, 2, 3, 4];
  2. let str = String.fromCharCode.apply(null, Array.from(arr));

建议改法

收起
自动换行
深色代码主题
复制
  1. let arr: number[] = [1, 2, 3, 4];
  2. let str = String.fromCharCode(...Array.from(arr));

bind定义方法

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: string = ''
  3. foo: Function = () => {}
  4. }
  5. class Test {
  6. value: string = '1234'
  7. obj: A = {
  8. value: this.value,
  9. foo: this.foo.bind(this)
  10. }
  11. foo() {
  12. console.log(this.value);
  13. }
  14. }

建议改法1

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: string = ''
  3. foo: Function = () => {}
  4. }
  5. class Test {
  6. value: string = '1234'
  7. obj: A = {
  8. value: this.value,
  9. foo: (): void => this.foo()
  10. }
  11. foo() {
  12. console.log(this.value);
  13. }
  14. }

建议改法2

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: string = ''
  3. foo: Function = () => {}
  4. }
  5. class Test {
  6. value: string = '1234'
  7. foo: () => void = () => {
  8. console.log(this.value);
  9. }
  10. obj: A = {
  11. value: this.value,
  12. foo: this.foo
  13. }
  14. }

使用apply

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: string;
  3. constructor (value: string) {
  4. this.value = value;
  5. }
  6. foo() {
  7. console.log(this.value);
  8. }
  9. }
  10. let a1 = new A('1');
  11. let a2 = new A('2');
  12. a1.foo();
  13. a1.foo.apply(a2);

建议改法

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: string;
  3. constructor (value: string) {
  4. this.value = value;
  5. }
  6. foo() {
  7. this.fooApply(this);
  8. }
  9. fooApply(a: A) {
  10. console.log(a.value);
  11. }
  12. }
  13. let a1 = new A('1');
  14. let a2 = new A('2');
  15. a1.foo();
  16. a1.fooApply(a2);

arkts-limited-stdlib

Object.fromEntries()

应用代码

收起
自动换行
深色代码主题
复制
  1. let entries = new Map([
  2. ['foo', 123],
  3. ['bar', 456]
  4. ]);
  5. let obj = Object.fromEntries(entries);

建议改法

收起
自动换行
深色代码主题
复制
  1. let entries = new Map([
  2. ['foo', 123],
  3. ['bar', 456]
  4. ]);
  5. let obj: Record<string, Object> = {};
  6. entries.forEach((value, key) => {
  7. if (key != undefined && key != null) {
  8. obj[key] = value;
  9. }
  10. })

使用Number的属性和方法

ArkTS不允许使用全局对象的属性和方法: Infinity, NaN, isFinite, isNaN, parseFloat, parseInt

可以使用Number的属性和方法: Infinity, NaN, isFinite, isNaN, parseFloat, parseInt

应用代码

收起
自动换行
深色代码主题
复制
  1. NaN;
  2. isFinite(123);
  3. parseInt('123');

建议改法

收起
自动换行
深色代码主题
复制
  1. Number.NaN;
  2. Number.isFinite(123);
  3. Number.parseInt('123');

arkts-strict-typing(StrictModeError)

strictPropertyInitialization

应用代码

收起
自动换行
深色代码主题
复制
  1. interface I {
  2. name:string
  3. }
  4. class A {}
  5. class Test {
  6. a: number;
  7. b: string;
  8. c: boolean;
  9. d: I;
  10. e: A;
  11. }

建议改法

收起
自动换行
深色代码主题
复制
  1. interface I {
  2. name:string
  3. }
  4. class A {}
  5. class Test {
  6. a: number;
  7. b: string;
  8. c: boolean;
  9. d: I = { name:'abc' };
  10. e: A | null = null;
  11. constructor(a:number, b:string, c:boolean) {
  12. this.a = a;
  13. this.b = b;
  14. this.c = c;
  15. }
  16. }

Type *** | null is not assignable to type ***

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. bar() {}
  3. }
  4. function foo(n: number) {
  5. if (n === 0) {
  6. return null;
  7. }
  8. return new A();
  9. }
  10. function getNumber() {
  11. return 5;
  12. }
  13. let a:A = foo(getNumber());
  14. a.bar();

建议改法

收起
自动换行
深色代码主题
复制
  1. class A {
  2. bar() {}
  3. }
  4. function foo(n: number) {
  5. if (n === 0) {
  6. return null;
  7. }
  8. return new A();
  9. }
  10. function getNumber() {
  11. return 5;
  12. }
  13. let a: A | null = foo(getNumber());
  14. a?.bar();

严格属性初始化检查

在class中,如果一个属性没有初始化,且没有在构造函数中被赋值,那么ArkTS将报错。

建议改法

1.一般情况下,建议按照业务逻辑在声明时初始化属性,或者在构造函数中为属性赋值。如:

收起
自动换行
深色代码主题
复制
  1. //code with error
  2. class Test {
  3. value: number
  4. flag: boolean
  5. }
  6. //方式一,在声明时初始化
  7. class Test {
  8. value: number = 0
  9. flag: boolean = false
  10. }
  11. //方式二,在构造函数中赋值
  12. class Test {
  13. value: number
  14. flag: boolean
  15. constructor(value: number, flag: boolean) {
  16. this.value = value;
  17. this.flag = flag;
  18. }
  19. }

2.对于对象类型(包括函数类型)A,如果不确定如何初始化,建议按照以下方式之一进行初始化

​ 方式(i) prop: A | null = null

​ 方式(ii) prop?: A

​ 方式三(iii) prop: A | undefined = undefined

  • 从性能角度来说,null类型只用在编译期的类型检查中,对虚拟机的性能无影响。而undefined | A被视为联合类型,运行时可能有额外的开销。
  • 从代码可读性、简洁性的角度来说,prop?:A是prop: A | undefined = undefined的语法糖,推荐使用可选属性的写法

严格函数类型检查

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo(fn: (value?: string) => void, value: string): void {}
  2. foo((value: string) => {}, ''); //error

建议改法

收起
自动换行
深色代码主题
复制
  1. function foo(fn: (value?: string) => void, value: string): void {}
  2. foo((value?: string) => {}, '');

原因

例如,在以下的例子中,如果编译期不开启严格函数类型的检查,那么该段代码可以编译通过,但是在运行时会产生非预期的行为。具体来看,在foo的函数体中,一个undefined被传入fn(这是可以的,因为fn可以接受undefined),但是在代码第6行foo的调用点,传入的(value: string) => { console.log(value.toUpperCase()) }的函数实现中,始终将参数value当做string类型,允许其调用toUpperCase方法。如果不开启严格函数类型的检查,那么这段代码在运行时,会出现在undefined上无法找到属性的错误。

收起
自动换行
深色代码主题
复制
  1. function foo(fn: (value?: string) => void, value: string): void {
  2. let v: string | undefined = undefined;
  3. fn(v);
  4. }
  5. foo((value: string) => { console.log(value.toUpperCase()) }, ''); // Cannot read properties of undefined (reading 'toUpperCase')

为了避免运行时的非预期行为,如果在编译时开启了严格类型检查,这段代码将编译不通过,从而可以提醒开发者修改代码,保证程序安全。

严格空值检查

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. private value?: string
  3. public printValue () {
  4. console.log(this.value.toLowerCase());
  5. }
  6. }
  7. let t = new Test();
  8. t.printValue();

建议改法

在编写代码时,建议减少可空类型的使用。如果对变量、属性标记了可空类型,那么在使用它们之间,需要进行空值的判断,根据是否为空值处理不同的逻辑。

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. private value?: string
  3. public printValue () {
  4. if (this.value) {
  5. console.log(this.value.toLowerCase());
  6. }
  7. }
  8. }
  9. let t = new Test();
  10. t.printValue();

原因

在第一段代码中,如果编译期不开启严格空值检查,那么该段代码可以编译通过,但是在运行时会产生非预期的行为。这是因为t的属性value为undefined(这是因为value?: string是value: string | undefined = undefined的语法糖),在第11行调用printValue方法时,由于在该方法体内未对this.value的值进行空值检查,而直接按照string类型访问其属性,这就导致了运行时的错误。为了避免运行时的非预期行为,如果在编译时开起来严格空值检查,这段代码将编译不通过从而可以提醒开发者修改代码(如按照第二段代码的方式),保证程序安全。

函数返回类型不匹配

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. handleClick: (action: string, externInfo?: string) => void | null = null;
  3. }

建议改法

在这种写法下,函数返回类型被解析为 void | undefined,需要添加括号用来区分union类型。

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. handleClick: ((action: string, externInfo?: string) => void) | null = null;
  3. }

'***' is of type 'unknown'

应用代码

收起
自动换行
深色代码主题
复制
  1. try {
  2. } catch (error) {
  3. console.log(error.message);
  4. }

建议改法

收起
自动换行
深色代码主题
复制
  1. import { BusinessError } from '@kit.BasicServicesKit'
  2. try {
  3. } catch (error) {
  4. console.log((error as BusinessError).message);
  5. }

Type '*** | null' is not assignable to type '***'

应用代码

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: number
  3. constructor(value: number) {
  4. this.value = value;
  5. }
  6. }
  7. function foo(v: number): A | null {
  8. if (v > 0) {
  9. return new A(v);
  10. }
  11. return null;
  12. }
  13. let a: A = foo();

建议改法1

修改变量a的类型:let a: A | null = foo()。

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: number
  3. constructor(value: number) {
  4. this.value = value;
  5. }
  6. }
  7. function foo(v: number): A | null {
  8. if (v > 0) {
  9. return new A(v);
  10. }
  11. return null;
  12. }
  13. let a: A | null = foo(123);
  14. if (a != null) {
  15. // 非空分支
  16. } else {
  17. // 处理null
  18. }

建议改法2

如果可以断定此处调用foo一定返回非空值,可以使用非空断言!。

收起
自动换行
深色代码主题
复制
  1. class A {
  2. value: number
  3. constructor(value: number) {
  4. this.value = value;
  5. }
  6. }
  7. function foo(v: number): A | null {
  8. if (v > 0) {
  9. return new A(v);
  10. }
  11. return null;
  12. }
  13. let a: A = foo(123)!;

Cannot invoke an object which possibly 'undefined'

应用代码

收起
自动换行
深色代码主题
复制
  1. interface A {
  2. foo?: () => void
  3. }
  4. let a:A = { foo: () => {} };
  5. a.foo();

建议改法1

收起
自动换行
深色代码主题
复制
  1. interface A {
  2. foo: () => void
  3. }
  4. let a: A = { foo: () => {} };
  5. a.foo();

建议改法2

收起
自动换行
深色代码主题
复制
  1. interface A {
  2. foo?: () => void
  3. }
  4. let a: A = { foo: () => {} };
  5. if (a.foo) {
  6. a.foo();
  7. }

原因

在原先代码的定义中,foo是可选属性,有可能为undefined,对undefined的调用会导致报错。建议按照业务逻辑判断是否需要为可选属性。如果确实需要,那么在访问到该属性后需要进行空值检查。

Variable '***' is used before being assigned

应用代码

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: number = 0
  3. }
  4. let a: Test
  5. try {
  6. a = { value: 1};
  7. } catch (e) {
  8. a.value;
  9. }
  10. a.value;

建议改法

收起
自动换行
深色代码主题
复制
  1. class Test {
  2. value: number = 0
  3. }
  4. let a: Test | null = null;
  5. try {
  6. a = { value:1 };
  7. } catch (e) {
  8. if (a) {
  9. a.value;
  10. }
  11. }
  12. if (a) {
  13. a.value;
  14. }

原因

对于primitive types,可以根据业务逻辑赋值,例如0,'',false。

对于对象类型,可以将类型修改为和null的联合类型,并赋值null,使用时需要进行非空检查。

Function lacks ending return statement and return type does not include 'undefined'.

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo(a: number): number {
  2. if (a > 0) {
  3. return a;
  4. }
  5. }

建议改法1

根据业务逻辑,在else分支中返回合适的数值

建议改法2

收起
自动换行
深色代码主题
复制
  1. function foo(a: number): number | undefined {
  2. if (a > 0) {
  3. return a;
  4. }
  5. return
  6. }

arkts-strict-typing-required

应用代码

收起
自动换行
深色代码主题
复制
  1. // @ts-nocheck
  2. var a: any = 123;

建议改法

收起
自动换行
深色代码主题
复制
  1. let a: number = 123;

原因

ArkTS不支持通过注释的方式绕过严格类型检查。首先将注释(// @ts-nocheck或者// @ts-ignore)删去,再根据报错信息修改其他代码。

Importing ArkTS files to JS and TS files is not allowed

arkts-no-tsdeps

不允许.ts、.js文件import.ets文件源码。

建议改法

方式1.将.ts文件的后缀修改成ets,按照ArkTS语法规则适配代码。

方式2.将.ets文件中被.ts文件依赖的代码单独抽取到.ts文件中。

arkts-no-special-imports

应用代码

收起
自动换行
深色代码主题
复制
  1. import type {A, B, C, D } from '***'

建议改法

收起
自动换行
深色代码主题
复制
  1. import {A, B, C, D } from '***'

arkts-no-classes-as-obj

使用class构造实例

应用代码

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value
  5. }
  6. }
  7. interface ControllerConstructor {
  8. new (value: string): Controller;
  9. }
  10. class Menu {
  11. controller: ControllerConstructor = Controller
  12. createController() {
  13. if (this.controller) {
  14. return new this.controller('abc');
  15. }
  16. return null;
  17. }
  18. }
  19. let t = new Menu();
  20. console.log(t.createController()!.value);

建议改法

收起
自动换行
深色代码主题
复制
  1. class Controller {
  2. value: string = ''
  3. constructor(value: string) {
  4. this.value = value
  5. }
  6. }
  7. type ControllerConstructor = () => Controller;
  8. class Menu {
  9. controller: ControllerConstructor = () => { return new Controller('abc'); }
  10. createController() {
  11. if (this.controller) {
  12. return this.controller();
  13. }
  14. return null;
  15. }
  16. }
  17. let t: Menu = new Menu();
  18. console.log(t.createController()!.value);

访问静态属性

应用代码

收起
自动换行
深色代码主题
复制
  1. class C1 {
  2. static value: string = 'abc'
  3. }
  4. class C2 {
  5. static value: string = 'def'
  6. }
  7. function getValue(obj: any) {
  8. return obj['value'];
  9. }
  10. console.log(getValue(C1));
  11. console.log(getValue(C2));

建议改法

收起
自动换行
深色代码主题
复制
  1. class C1 {
  2. static value: string = 'abc'
  3. }
  4. class C2 {
  5. static value: string = 'def'
  6. }
  7. function getC1Value(): string {
  8. return C1.value;
  9. }
  10. function getC2Value(): string {
  11. return C2.value;
  12. }
  13. console.log(getC1Value());
  14. console.log(getC2Value());

arkts-no-side-effects-imports

改用动态import

应用代码

收起
自动换行
深色代码主题
复制
  1. import 'module'

建议改法

收起
自动换行
深色代码主题
复制
  1. import('module')

arkts-no-func-props

应用代码

收起
自动换行
深色代码主题
复制
  1. function foo(value: number): void {
  2. console.log(value.toString());
  3. }
  4. foo.add = (left: number, right: number) => {
  5. return left + right;
  6. }
  7. foo.sub = (left: number, right: number) => {
  8. return left - right;
  9. }

建议改法

收起
自动换行
深色代码主题
复制
  1. class Foo {
  2. static foo(value: number): void {
  3. console.log(value.toString());
  4. }
  5. static add(left: number, right: number): number {
  6. return left + right;
  7. }
  8. static sub(left: number, right: number): number {
  9. return left - right;
  10. }
  11. }

arkts-limited-esobj

应用代码

收起
自动换行
深色代码主题
复制
  1. // lib.d.ts
  2. declare function foo(): any;
  3. // main.ets
  4. let e0: ESObject = foo();
  5. function f() {
  6. let e1 = foo();
  7. let e2: ESObject = 1;
  8. let e3: ESObject = {};
  9. let e4: ESObject = '';
  10. }

建议改法

收起
自动换行
深色代码主题
复制
  1. // lib.d.ts
  2. declare function foo(): any;
  3. // main.ets
  4. interface I {}
  5. function f() {
  6. let e0: ESObject = foo();
  7. let e1: ESObject = foo();
  8. let e2: number = 1;
  9. let e3: I = {};
  10. let e4: string = '';
  11. }

拷贝

浅拷贝

TypeScript

收起
自动换行
深色代码主题
复制
  1. function shallowCopy(obj: object): object {
  2. let newObj = {};
  3. Object.assign(newObj, obj);
  4. return newObj;
  5. }

ArkTS

收起
自动换行
深色代码主题
复制
  1. function shallowCopy(obj: object): object {
  2. let newObj: Record<string, Object> = {};
  3. for (let key of Object.keys(obj)) {
  4. newObj[key] = obj[key];
  5. }
  6. return newObj;
  7. }

深拷贝

TypeScript

收起
自动换行
深色代码主题
复制
  1. function deepCopy(obj: object): object {
  2. let newObj = Array.isArray(obj) ? [] : {};
  3. for (let key in obj) {
  4. if (typeof obj[key] === 'object') {
  5. newObj[key] = deepCopy(obj[key]);
  6. } else {
  7. newObj[key] = obj[key];
  8. }
  9. }
  10. return newObj;
  11. }

ArkTS

收起
自动换行
深色代码主题
复制
  1. function deepCopy(obj: object): object {
  2. let newObj: Record<string, Object> | Object[] = Array.isArray(obj) ? [] : {};
  3. for (let key of Object.keys(obj)) {
  4. if (typeof obj[key] === 'object') {
  5. newObj[key] = deepCopy(obj[key]);
  6. } else {
  7. newObj[key] = obj[key];
  8. }
  9. }
  10. return newObj;
  11. }

状态管理使用典型场景

Struct组件外使用状态变量

由于struct和class不同,不建议把this作为参数传递到struct外部使用,避免引起实例引用无法释放的情况,导致内存泄露。建议将状态变量对象传递到struct外面使用,通过修改对象的属性,来触发UI刷新。

不推荐用法

收起
自动换行
深色代码主题
复制
  1. export class MyComponentController {
  2. item: MyComponent = null;
  3. setItem(item: MyComponent) {
  4. this.item = item;
  5. }
  6. changeText(value: string) {
  7. this.item.value = value;
  8. }
  9. }
  10. @Component
  11. export default struct MyComponent {
  12. public controller: MyComponentController = null;
  13. @State value: string = 'Hello World';
  14. build() {
  15. Column() {
  16. Text(this.value)
  17. .fontSize(50)
  18. }
  19. }
  20. aboutToAppear() {
  21. if (this.controller)
  22. this.controller.setItem(this); // 不建议把this作为参数传递到struct外部使用
  23. }
  24. }
  25. @Entry
  26. @Component
  27. struct ObjThisOldPage {
  28. controller = new MyComponentController();
  29. build() {
  30. Column() {
  31. MyComponent({ controller: this.controller })
  32. Button('change value').onClick(() => {
  33. this.controller.changeText('Text');
  34. })
  35. }
  36. }
  37. }

推荐用法

收起
自动换行
深色代码主题
复制
  1. class CC {
  2. value: string = '1';
  3. constructor(value: string) {
  4. this.value = value;
  5. }
  6. }
  7. export class MyComponentController {
  8. item: CC = new CC('1');
  9. setItem(item: CC) {
  10. this.item = item;
  11. }
  12. changeText(value: string) {
  13. this.item.value = value;
  14. }
  15. }
  16. @Component
  17. export default struct MyComponent {
  18. public controller: MyComponentController | null = null;
  19. @State value: CC = new CC('Hello World');
  20. build() {
  21. Column() {
  22. Text(`${this.value.value}`)
  23. .fontSize(50)
  24. }
  25. }
  26. aboutToAppear() {
  27. if (this.controller)
  28. this.controller.setItem(this.value);
  29. }
  30. }
  31. @Entry
  32. @Component
  33. struct StyleExample {
  34. controller: MyComponentController = new MyComponentController();
  35. build() {
  36. Column() {
  37. MyComponent({ controller: this.controller })
  38. Button('change value').onClick(() => {
  39. this.controller.changeText('Text');
  40. })
  41. }
  42. }
  43. }

Struct支持联合类型的方案

下面这段代码有arkts-no-any-unknown的报错,由于struct不支持泛型,建议使用联合类型,实现自定义组件类似泛型的功能。

不推荐用法

收起
自动换行
深色代码主题
复制
  1. class Data {
  2. aa: number = 11;
  3. }
  4. @Entry
  5. @Component
  6. struct DatauionOldPage {
  7. @State array: Data[] = [new Data(), new Data(), new Data()];
  8. @Builder
  9. componentCloser(data: Data) {
  10. Text(data.aa + '').fontSize(50)
  11. }
  12. build() {
  13. Row() {
  14. Column() {
  15. ForEachCom({ arrayList: this.array, closer: this.componentCloser })
  16. }
  17. .width('100%')
  18. }
  19. .height('100%')
  20. }
  21. }
  22. @Component
  23. export struct ForEachCom {
  24. arrayList: any[]; // struct不支持泛型,有arkts-no-any-unknown报错
  25. @BuilderParam closer: (data: any) => void = this.componentCloser; // struct不支持泛型,有arkts-no-any-unknown报错
  26. @Builder
  27. componentCloser() {
  28. }
  29. build() {
  30. Column() {
  31. ForEach(this.arrayList, (item: any) => { // struct不支持泛型,有arkts-no-any-unknown报错
  32. Row() {
  33. this.closer(item)
  34. }.width('100%').height(200).backgroundColor('#eee')
  35. })
  36. }
  37. }
  38. }

推荐用法

收起
自动换行
深色代码主题
复制
  1. class Data {
  2. aa: number = 11;
  3. }
  4. class Model {
  5. aa: string = '11';
  6. }
  7. type UnionData = Data | Model;
  8. @Entry
  9. @Component
  10. struct DatauionPage {
  11. array: UnionData[] = [new Data(), new Data(), new Data()];
  12. @Builder
  13. componentCloser(data: UnionData) {
  14. if (data instanceof Data) {
  15. Text(data.aa + '').fontSize(50)
  16. }
  17. }
  18. build() {
  19. Row() {
  20. Column() {
  21. ForEachCom({ arrayList: this.array, closer: this.componentCloser })
  22. }
  23. .width('100%')
  24. }
  25. .height('100%')
  26. }
  27. }
  28. @Component
  29. export struct ForEachCom {
  30. arrayList: UnionData[] = [new Data(), new Data(), new Data()];
  31. @BuilderParam closer: (data: UnionData) => void = this.componentCloser;
  32. @Builder
  33. componentCloser() {
  34. }
  35. build() {
  36. Column() {
  37. ForEach(this.arrayList, (item: UnionData) => {
  38. Row() {
  39. this.closer(item)
  40. }.width('100%').height(200).backgroundColor('#eee')
  41. })
  42. }
  43. }
  44. }
在 指南 中进行搜索
请输入您想要搜索的关键词