ArkTS1.2与ArkTS1.1互操作规范
ArkTS1.1中使用ArkTS1.2
ArkTS1.2导出ArkTS1.1实体
规则: arkts-interop-d2s-export-entity
级别: error
ArkTS1.1
// file1.ets
export function foo() {}
export class X {}
export interface Y {}
// file2.ets
import { foo } from './file1';
export { foo };
export { X, Y } from './file1';
ArkTS1.2
// file1.ets ArkTS1.1
export function foo() {}
export class X {}
export interface Y {}
// file2.ets ArkTS1.2
'use static'
import { foo } from './file1';
export { foo }; // 编译报错
export { X, Y } from './file2'; // 编译报错
ArkTS1.2判断ArkTS1.1 boxed type类型
规则: arkts-interop-d2s-boxed-type
级别: error
ArkTS1.1
// file1.ets
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
//file2.ets
import { a, b, c } from './fiel1';
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'number'
typeof b; // 'boolean'
typeof c; // 'string'
//file2.ets ArkTS1.1
import { a, b, c } from './fiel1';
typeof a; // 'number'
typeof b; // 'boolean'
typeof c; // 'string'
ArkTS1.2使用ArkTS1.1的@Sendable和@Concurrent
规则: arkts-interop-d2s-no-concurrent-decorators
级别: error
ArkTS1.1
// file1.ets
@Sendable
class X {}
@Concurrent
function foo() {}
ArkTS1.2
// file1.ets
'use static'
class X {}
function foo() {}
ArkTS1.1 Object内置方法作用在ArkTS1.2对象
规则: arkts-interop-d2s-dynamic-object-on-static-instance
级别: error
ArkTS1.1
// file1.ets
export function foo(prx: Object) {
Object.getOwnPropertyNames(prx); // ["a"]
Object.hasOwn(prx, 'a'); // true
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
// file2.ets
import { foo } from './file1';
class X {
a = 1;
}
foo(new X());
ArkTS1.2
// Object.keys的解决方案,与Object.values的情况类似
// file0.ets ArkTS1.2
'use static'
export function getKeys(prx: Object | ESValue): string[] | undefined {
if (prx instanceof Object) {
return Object.keys(prx);
}
return undefined;
}
// file1.ets ArkTS1.1
import { getKeys } from './file0';
function myGetKeys(prx: Object) {
let ret = getKeys(prx);
if (ret == undefined) {
// prx is dynamic
return Object.keys(prx);
}
return ret;
}
export function foo(prx: Object) {
Object.getOwnPropertyNames(prx); // []
Object.hasOwn(prx, 'a'); // false
Object.keys(prx); // []
myGetKeys(prx); // ['a']
Object.values(prx); // []
}
// file2.ets ArkTS1.2
'use static'
import { foo } from './file1';
class X {
a = 1;
}
foo(new X());
ArkTS1.1 Reflect内置方法作用在ArkTS1.2对象
规则: arkts-interop-d2s-dynamic-reflect-on-static-instance
级别: error
ArkTS1.1
// file1.ets
import { foo } from './file1';
export class X {
a: string = 'hello';
getName() {
return this.a;
}
}
// file2.ets
import { X } from './file1';
function foo(prx: Object) {
Reflect.ownKeys(prx); // ['a']
Reflect.set(prx, 'newField', 7); // true
}
foo(new X());
ArkTS1.2
// static ownKeys的解决方案
// file0.ets ArkTS1.2
'use static'
export getOwnKeys(prx: Object | ESValue): string[] | undefined {
if (prx instanceof Object) { return Reflect.ownKeys(prx) }
return undefined
}
// file1.ets ArkTS1.1
import { getOwnKeys } from './file0'
export function myOwnKeys(prx: Object) {
let ret = getOwnKeys(prx)
if (ret == undefined) { // prx是动态对象
return Reflect.ownKeys(prx)
}
return ret
}
export function foo(prx: Object) {
Reflect.ownKeys(prx) // []
myOwnKeys(prx) // ['a']
Reflect.set(prx, 'newField', 7) // false
}
// file2.ets ArkTS1.2
'use static'
import { foo } from './file1'
export class X {
a: string = 'hello'
getName() { return this.a }
}
foo(new X())
ArkTS1.2Object内置方法作用在ArkTS1.1对象
规则: arkts-interop-d2s-static-object-on-dynamic-instance
级别: error
ArkTS1.1
// file1.ets
export class X {
a = 1;
}
// file2.ets
import { X } from 'file1';
export function foo(prx: Object) {
Object.entries(prx); // [a, 1]
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
foo(new X());
ArkTS1.2
// file1.ets ArkTS1.1
export class X {
a = 1;
}
// file2.ets ArkTS 1.2
'use static'
import { X } from 'file1';
export function foo(prx: Object) {
Object.entries(prx); // [a, 1]
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
foo(new X()); // 编译报错
ArkTS1.2Reflect内置方法作用在ArkTS1.1对象
规则: arkts-interop-d2s-static-reflect-on-dynamic-instance
级别: error
ArkTS1.1
// file1.ets ArkTS1.1
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
// file2.ets ArkTS1.2
'use static'
import { X } from './file1';
export function foo(prx: Object) {
Reflect.get(prx, 'a'); // 'hello'
Reflect.set(prx, 'a', 'world'); // true
Reflect.ownKeys(prx); // ['a']
}
foo(new X());
ArkTS1.2
// file1.ets ArkTS1.1
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
// file2.ets ArkTS1.2
'use static'
import { X } from './file1';
export function foo(prx: Object) {
Reflect.get(prx, 'a'); // 'hello'
Reflect.set(prx, 'a', 'world'); // true
Reflect.ownKeys(prx); // ['a']
}
foo(new X()); // 编译报错
ArkTS1.2动态导入ArkTS1.1
规则: arkts-interop-d2s-dynamic-import
级别: error
ArkTS1.1
// file1.ets
export class A {}
// file2.ets
let mod = await import('./file1');
let A: ESValue = mod.A;
let a = new A() as A;
// 动态导入class、function、enum变量
ArkTS1.2
// file1.ets ArkTS1.1
export class A {}
// file2.ets ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let A: ESValue = mod.getProperty('A');
let a = A.instantiate() as A;
ArkTS1.2创建ArkTS1.1的没有无参构造函数的类的对象字面量
规则: arkts-interop-d2s-object-literal-no-args-constructor
级别: error
ArkTS1.1
// file1.ets
export class X {
name: string;
constructor(arg: string) {
this.name = arg;
}
}
// file2.ets
import { X } from './file1';
let x = new X('hello');
ArkTS1.2
// file1.ets ArkTS1.1
export class X {
name: string;
constructor(arg: string) {
this.name = arg;
}
}
// file2.ets ArkTS1.2
'use static'
import { X } from './file1';
let x: X = new X('hello') // 编译报错
ArkTS1.2创建ArkTS1.1具有二义性的对象字面量
规则: arkts-interop-d2s-object-literal-no-ambiguity
级别: error
当一个对象的类型被声明为联合类型,而右侧实际赋值的是一个类的实例时,会引发类型系统的二义性(对象可以是联合类型的任一类型,但实际运行时明确是一个类的实例,这种差异会导致类型检查或运行时的不确定性)。
ArkTS1.1
// file1.ets
export class X {
name: string = '';
}
export interface Y {
name: string;
age?: number;
}
// file2.ets
import { X, Y } from './file1';
let x: X | Y = { name: 'hello' };
ArkTS1.2
// file1.ets // 1.0
export class X {
name: string = '';
}
export interface Y {
name: string;
age?: number;
}
// file2.ets // 1.2
'use static'
import { X, Y } from './file1';
let x: X | Y = { name: 'hello' }; //编译报错
let x: X | Y = new X('hello'); // OK
ArkTS1.2创建ArkTS1.1的类的对象字面量
规则: arkts-interop-d2s-object-literal
级别: error
ArkTS1.1
// file1.ets
export class A {
name: string = '';
}
// file2.ets
import { A } from './file1';
let a: A = { name: 'hello' }; // a是创建的对象自变量
a instanceof A; // false
ArkTS1.2
// file1.ets ArkTS1.1
export class A {
name: string = '';
}
// file2.ets ArkTS1.2
'use static'
import { A } from './file1';
let a: A = { name: 'hello' }; // a是创建的对象
a instanceof A; // true
ArkTS1.2中使用ArkTS1.1
ArkTS1.1判断ArkTS1.2 boxed类型
规则: arkts-interop-s2d-boxed-type
级别: error
ArkTS1.1
// file1.ets
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
//file2.ets
import { a, b, c } from './fiel1';
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'number'
typeof b; // 'boolean'
typeof c; // 'string'
//file2.ets ArkTS1.1
import { a, b, c } from './fiel1';
typeof a; // 'number'
typeof b; // 'boolean'
typeof c; // 'string'
ArkTS1.1创建ArkTS1.2对象字面量
规则: arkts-interop-s2d-object-literal
级别: error
ArkTS1.1
// file1.ets
export class X {
name: string = '';
constructor(arg: string) {
this.name = arg;
}
}
export interface Y {
data: number;
}
export type MyRecord = Record<string, number>;
export function foo(arg: X) {}
export function bar(arg: Y) {}
// file2.ets
import { X, Y } from './file1';
let x = { name: 'hello' };
let y: Y = { data: 123 };
foo({ name: 'world' });
bar({ data: 456 });
// 返回值 zoo(): X { return {..}}
// 嵌套场景
interface Z {
x: X;
}
let z: Z = {x: { name: 'hello' }};
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export class X { name: string = '' }
export interface Y { data: number }
export function foo(arg: X) { }
export function bar(arg: Y) { }
export function createY(d: number): Y {
let y: Y = { data: d }
return y
}
// file2.ets ArkTS1.1
import { X, Y, createY } from "./file1"
let x: X = new X("hello")
let y: Y = createY(123)
foo(new X("world"))
bar(createY(456))
ArkTS1.1传参或赋值给ArkTS1.2
规则: arkts-interop-s2d-dynamic-args-to-static
级别: error
ArkTS1.1
// file1.ets
export function foo(obj: Object) {}
export class A {
data: Object = 0;
}
// file2.ets
import { foo, A } from './file1';
class X {}
foo(new X());
interface Y {
s: string;
}
let y: Y = { s: 'Hi' };
let a = new A();
a.data = y;
// 动态对象的来源:class/interface/对象字面量
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export function foo(obj: Object) {}
// solution: export function foo(obj: ESValue | Object) {}
export class A {
data: Object = 0;
}
// solution: export class A { data: ESValue = ESValue.wrap(0) }
// file2.ets ArkTS1.1
import { foo, A } from './file1';
class X {}
foo(new X()); // 运行时报错
interface Y {
s: string;
}
let y: Y = { s: 'Hi' };
let a = new A();
a.data = y; // 运行时报错
ArkTS1.1 Object内置方法作用在ArkTS1.2对象
规则: arkts-interop-s2d-dynamic-object-on-static-instance
级别: error
ArkTS1.1
// file2.ets
export class X {
a = 1;
}
// file1.ets
import { X } from './file2';
function foo(prx: Object) {
Object.getOwnPropertyNames(prx); // ["a"]
Object.hasOwn(prx, 'a'); // true
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
foo(new X());
ArkTS1.2
// file2.ets ArkTS1.2
'use static'
export class X {
a = 1;
}
// Object.keys的解决方案,与Object.values的情况类似
export function getKeys(prx: Object | ESValue): string[] | undefined {
if (prx instanceof Object) {
return Object.keys(prx);
}
return undefined;
}
// file1.ets ArkTS1.1
import { X, getKeys } from './file2';
function myGetKeys(prx: Object) {
let ret = getKeys(prx);
if (ret == undefined) {
// prx is dynamic
return Object.keys(prx);
}
return ret;
}
export function foo(prx: Object) {
Object.getOwnPropertyNames(prx); // []
Object.hasOwn(prx, 'a'); // false
Object.keys(prx); // []
myGetKeys(prx); // ['a']
Object.values(prx); // []
}
foo(new X());
ArkTS1.1 Reflect内置方法作用在ArkTS1.2对象
规则: arkts-interop-s2d-dynamic-reflect-on-static-instance
级别: error
ArkTS1.1
// file2.ets
export class X {
a: string = 'hello';
getName() {
return this.a;
}
}
// file1.ets
import { X } from './file2';
function foo(prx: Object) {
Reflect.ownKeys(prx); // ['a']
Reflect.set(prx, 'newField', 7); // true
}
foo(new X());
ArkTS1.2
// file2.ets ArkTS1.2
'use static'
export class X {
a: string = 'hello'
getName() { return this.a }
}
// static ownKeys的解决方案
export getOwnKeys(prx: Object | ESValue): string[] | undefined {
if (prx instanceof Object) { return Reflect.ownKeys(prx) }
return undefined
}
// file1.ets ArkTS1.1
import { X, getOwnKeys } from "./file2"
function myOwnKeys(prx: Object) {
let ret = getOwnKeys(prx)
if (ret == undefined) { // prx is dynamic
return Reflect.ownKeys(prx)
}
return ret
}
function foo(prx: Object) {
Reflect.ownKeys(prx) // []
myOwnKeys(prx) // ['a']
Reflect.set(prx, 'newField', 7) // false
}
foo(new X())
ArkTS1.2Object内置方法作用在ArkTS1.1对象
规则: arkts-interop-s2d-static-object-on-dynamic-instance
级别: error
ArkTS1.1
// file1.ets
export function foo(prx: Object) {
Object.entries(prx); // [a, 1]
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
// file2.ets
import { foo } from './file1';
class X {
a = 1;
}
foo(new X());
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export function foo(prx: Object) {
Object.entries(prx); // [a, 1]
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
// file2.ets ArkTS1.1
import { foo } from './file1';
class X {
a = 1;
}
foo(new X()); // 运行时报错
ArkTS1.2Reflect内置方法作用在ArkTS1.1对象
规则: arkts-interop-s2d-static-reflect-on-dynamic-instance
级别: error
ArkTS1.1
// file1.ets
export function foo(prx: Object) {
Reflect.get(prx, 'a'); // 'hello'
Reflect.set(prx, 'a', 'world'); // true
Reflect.ownKeys(prx); // ['a']
}
// file2.ets
import { foo } from './file1';
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo(new X());
ArkTS1.2
// file1.ets ArkTS1.2
'use static'
export function foo(prx: Object) {
Reflect.get(prx, 'a'); // 'hello'
Reflect.set(prx, 'a', 'world'); // true
Reflect.ownKeys(prx); // ['a']
}
// file2.ets ArkTS1.1
import { foo } from './file1';
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo(new X()); // 运行时报错
ArkTS1.1代码调用ArkTS1.2中废弃的方法
规则: arkts-interop-s2d-dynamic-call-builtin-api-not-in-static
级别: error
在ArkTS1.1代码中导入ArkTS1.2的Builtin类型对象,并调用一个在ArkTS1.2版本中已被移除(但在1.1中仍存在)的方法,导致潜在的兼容性问题出现。
ArkTS1.1
// file1.ets ArkTS 1.1
export let arr: Array<number> = new Array<number>(1, 2, 3);
// file2.ets ArkTS 1.1
import {arr} from "./file1"
class C {
base: number;
constructor(base:number) {
this.base = base;
}
compare(value: number, index: number, arr: Array<number>) {
return value >= this.base
}
}
let a = new C(2);
let b = new C(3);
arr.find(a.compare, a) // Result: 2
arr.find(a.compare, b) // Result: 3
ArkTS1.2
// file1.ets ArkTS 1.2
'use static'
export let arr: Array<number> = new Array<number>(1, 2, 3);
// file2.ets ArkTS 1.1
import {arr} from "./file1"
class C {
base: number;
constructor(base:number) {
this.base = base;
}
compare(value: number, index: number, arr: Array<number>) {
return value >= this.base
}
}
let a = new C(2);
let b = new C(3);
arr.find(a.compare, a) // 运行时报错
arr.find(a.compare, b) // 运行时报错
ArkTS1.2中使用TS
ArkTS1.2使用TS装饰器
规则: arkts-interop-ts2s-no-ts-decorator
级别: error
ArkTS1.1
// file1.ts
export function MyClassDecorator(klass: Object) {}
// file2.ets
import { MyClassDecorator } from './file1';
@MyClassDecorator
class K {}
ArkTS1.2
NA;
ArkTS1.2访问TS独有类型的实体
规则: arkts-interop-ts2s-static-access-ts-type
TS独有类型包括如下类型:
- any
- unknown
- symbol
- Function
- object literal (例如 {x: number, y: string})
- mixing enum (例如 enum X {a = 0, b = '1'})
- call signature (例如 {(arg: number): string})
- constructor signature (例如 {new(): Object})
- index signature (例如 {[index: number]: string})
- intersection (例如 TypeA & TypeB)
- keyof (例如 interface X { props: keyof T})
- typeof(例如 let p = {x: 1, y: ''}, let q: typeof p)
- indexed access type(例如 MyArray = [{ name: "Alice", age: 15 }] type Person = typeof MyArray[number])
- conditional types (例如 type Swap<T extends A | B> = T extends A ? B : A)
- mapped types (例如 type A = {[K in keyof T]: T[K]})
- template literal types (例如 type AB = "A" | "B", type AllLocaleIDs =
${AB}_id) - Pick<Type, Keys>
- Omit<Type, Keys>
- Exclude<UnionType, ExcludedMembers>
- Extract<Type, Union>
- NonNullable
- Parameters
- ConstructorParameters
- ReturnType
- InstanceType
- NoInfer
- ThisParameterType
- OmitThisParameter
- ThisType
- Uppercase
- Lowercase
- Capitalize
- Uncapitalize
级别: error
ArkTS1.1
// file1.ts
export let obj: Symbol;
// file2.ets
import { obj } from './file1';
let val = obj.prop;
obj.prop = 1;
obj.foo();
let item = obj[0];
ArkTS1.2
// file1.ts
export let obj: Symbol;
// 从ArkTS1.2看来,这个声明为
// export let obj: ESValue
// file2.ets ArkTS1.2
'use static'
import { obj } from './file1';
obj.setProperty('prop', ESValue.wrap(1));
ArkTS1.1Object内置方法作用在ArkTS1.2对象
规则: arkts-interop-ts2s-ts-object-on-static-instance
级别: error
ArkTS1.1
// file1.ts
export function foo(prx: any) {
Object.getOwnPropertyNames(prx); // ["a"]
Object.hasOwn(prx, 'a'); // true
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
// file2.ets
import { foo } from './file1';
class X {
a = 1;
}
foo(new X());
ArkTS1.2
// file1.ts
export function foo(prx: any) {
Object.getOwnPropertyNames(prx) // []
Object.hasOwn(prx, "a") // false
Object.keys(prx) // []
Object.values(prx) // []
}
// file2.ets
'use static'
import {foo} from "./file1"
class X { a = 1 }
foo(ESValue.wrap(new X()))
ArkTS1.1Reflect内置方法作用在ArkTS1.2对象
规则: arkts-interop-ts2s-ts-reflect-on-static-instance
级别: error
ArkTS1.1
// file1.ts
export function foo(prx: any) {
Reflect.ownKeys(prx); // ['a']
Reflect.set(prx, 'newField', 7); // true
}
// file2.ets
import { foo } from './file1';
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo(new X());
ArkTS1.2
// file1.ts
export function foo(prx: any) {
Reflect.ownKeys(prx); // []
Reflect.set(prx, 'newField', 7); // false
}
// file2.ets
'use static'
import { foo } from './file1';
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo(ESValue.wrap(new X()));
ArkTS1.2处理TS非常规异常
规则: arkts-interop-ts2s-ts-exception
级别: error
ArkTS1.1
// file1.ts
export function foo() {
throw 123;
}
// file2.ets
import { foo } from './file1';
try {
foo();
} catch (e) {
console.log("result is " + (e as number)); // 123
}
ArkTS1.2
// file1.ts
export function foo() {
throw 123;
}
// file2.ets // ArkTS1.2
'use static'
import { foo } from './file1';
try {
foo();
} catch (e) {
let err: ESValue = (e as ESError).getValue();
err.toNumber(); // 123
}
ArkTS1.2判断ArkTS1.1 boxed type类型
规则: arkts-interop-ts2s-boxed-type
级别: error
ArkTS1.1
// file1.ts
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
//file2.ets
import { a, b, c } from './fiel1';
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
ArkTS1.2
// file1.ts
export let a = new Number(123);
export let b = new Boolean(true);
export let c = new String('hello');
typeof a; // 'object'
typeof b; // 'object'
typeof c; // 'object'
//file2.ets ArkTS1.2
'use static'
import { a, b, c } from './fiel1';
typeof a; // 'number'
typeof b; // 'boolean'
typeof c; // 'string'
ArkTS1.2动态导入TS
规则: arkts-interop-ts2s-dynamic-import-ts
级别: error
ArkTS1.1
// file1.ts
export class A {}
// file2.ets
let mod = await import('./file1');
let A: ESValue = mod.A;
let a = new A() as A;
ArkTS1.2
// file1.ets ts
export class A {}
// file2.ets ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let A: ESValue = mod.getProperty('A');
let a = A.instantiate() as A;
ArkTS1.2创建TS的类的对象字面量
规则: arkts-interop-ts2s-object-literal
级别: error
ArkTS1.1
// file1.ts
export class A {
name: string = '';
}
// file2.ets
import { A } from './file1';
let a: A = { name: 'hello' };
a instanceof A; // false
ArkTS1.2
// file1.ts
export class A {
name: string = '';
}
// file2.ets ArkTS1.2
'use static'
import { A } from './file1';
let a: A = { name: 'hello' };
a instanceof A; // true
ArkTS1.2中使用JS
ArkTS1.2导入js文件
规则: arkts-interop-js2s-import-js
级别: error
ArkTS1.1
// file1.js
export function foo() {}
// file2.ets
import { foo } from './file1';
ArkTS1.2
// file1.js
export function foo() {}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
ArkTS1.2导出js实体
规则: arkts-interop-js2s-export-js
级别: error
ArkTS1.1
// file1.js
export function foo() {}
export class A {}
// file2.ets
import { foo } from './file1';
export { foo };
export { A } from './file1';
// 函数、类、变量、枚举
ArkTS1.2
// file1.js
export function foo() {}
export class A {}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let A = mod.getProperty('A');
export { foo, A };
ArkTS1.2调用js函数和传参
规则: arkts-interop-js2s-call-js-func
级别: error
ArkTS1.1
// file1.js
export function foo() {}
export function bar(a) {}
// file2.ets
import { foo, bar } from './file1';
foo();
bar(123);
ArkTS1.2
// file1.js
export function foo() {}
export function bar(a) {}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let bar = mod.getProperty('bar');
foo.invoke();
bar.invoke(ESValue.wrap(123));
ArkTS1.2实例化js对象
规则: arkts-interop-js2s-create-js-instance
级别: error
ArkTS1.1
// file1.js
class foo {
constructor(a) {}
}
// file2.ets
import { foo } from './file1';
new foo(123);
ArkTS1.2
// file1.js
class foo {
constructor(a) {}
}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
foo.instantiate(ESValue.wrap(123));
ArkTS1.2访问js属性
规则: arkts-interop-js2s-access-js-prop
级别: error
ArkTS1.1
// file1.js
export let foo = { name: '123' };
// file2.ets
import { foo } from './file1';
foo.name;
foo.name = '456';
ArkTS1.2
// file1.js
export let foo = {name: "123"}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1')
let foo = mod.getProperty('foo')
foo.getProperty('name')
foo.setProperty('name', ESValue.wrap("456"))
ArkTS1.2调用js方法和传参
规则: arkts-interop-js2s-call-js-method
级别: error
ArkTS1.1
// file1.js
class Foo {
bar(a) {}
}
export let foo = new Foo();
// file2.ets
import { foo } from './file1';
foo.bar(123);
ArkTS1.2
// file1.js
class Foo {
bar(a) {}
}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
foo.invokeMethod('bar', ESValue.wrap(123));
ArkTS1.2访问js索引
规则: arkts-interop-js2s-access-js-index
级别: error
ArkTS1.1
// file1.js
export let foo = { arr: [1, 2, 3] };
// file2.ets
import { foo } from './file1';
let arr = foo.arr;
arr[1];
arr[3] = 4;
ArkTS1.2
// file1.js
export let foo = [1, 2, 3];
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let arr = foo.getProperty('arr');
arr.getProperty(1);
arr.setProperty(3, ESValue.wrap(4));
ArkTS1.2转换js对象类型
规则: arkts-interop-js2s-convert-js-type
级别: error
ArkTS1.1
// file1.js
export let foo1 = { num: 123 };
export let foo2 = { bool: true };
export let foo3 = { str: '123' };
export let foo4 = { big: 123n };
// file2.ets
import { foo } from './file1';
let a: number = foo1.num as number;
let b: boolean = foo2.bool as boolean;
let c: string = foo3.str as string;
let d: bigint = foo4.big as bigint;
ArkTS1.2
// file1.js
export let foo1 = { num: 123 };
export let foo2 = { bool: true };
export let foo3 = { str: '123' };
export let foo4 = { big: 123n };
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo1 = mod.getProperty('foo1');
let num = foo1.getProperty('num');
let a1: number = num.toNumber();
let foo2 = mod.getProperty('foo2');
let bool = foo2.getProperty('bool');
let a2: boolean = bool.toBoolean();
let foo3 = mod.getProperty('foo3');
let str = foo3.getProperty('str');
let a3: string = str.toString();
let foo4 = mod.getProperty('foo4');
let big = foo4.getProperty('big');
let a4: bigint = big.toBigInt();
ArkTS1.2获取js对象类型
规则: arkts-interop-js2s-typeof-js-type
级别: error
ArkTS1.1
// file1.js
export let foo = { num: 123 };
// file2.ets
import { foo } from './file1';
typeof foo.num; // 'number'
ArkTS1.2
// file1.js
export let foo = 123;
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let num = foo.getProperty('num');
num.typeOf(); // 'number'
ArkTS1.2判断js对象类型
规则: arkts-interop-js2s-instanceof-js-type
级别: error
ArkTS1.1
// file1.js
export class Foo {}
export let foo = new Foo();
// file2.ets
import { Foo, foo } from './file1';
foo instanceof Foo;
ArkTS1.2
// file1.js
export class Foo {}
export let foo = new Foo();
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let Foo = mod.getProperty('Foo');
let foo = mod.getProperty('foo');
foo.isInstanceOf(Foo);
ArkTS1.2对js对象自增自减
规则: arkts-interop-js2s-self-addtion-reduction
级别: error
ArkTS1.1
// file1.js
export let foo = { num: 0 };
// file2.ets
import { foo } from './file1';
let a: number = 0;
a = foo.num++;
a = ++foo.num;
a = foo.num--;
a = --foo.num;
ArkTS1.2
// file1.js
export let foo = { num: 0 };
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let a: number = 0;
// a = foo.num++
let num = foo.getProperty('num');
let tmp: number = num.toNumber();
a = tmp;
foo.setProperty('num', ESValue(tmp + 1));
// a = ++foo.num
num = foo.getProperty('num');
tmp = num.toNumber() + 1;
foo.setProperty('num', ESValue(tmp));
a = tmp;
// the cases "foo.num--" and "--foo.num" are similar
ArkTS1.2对js对象进行一元运算
规则: arkts-interop-js2s-unary-op
级别: error
ArkTS1.1
// file1.js
export let foo = { num: 0 };
// file2.ets
import { foo } from './file1';
+foo.num;
-foo.num;
!foo.num;
~foo.num;
ArkTS1.2
// file1.js
export let foo = { num: 0 };
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let num = foo.getProperty('num');
// +foo.num
+num.toNumber();
// -foo.num
-num.toNumber();
// !foo.num
!num.toNumber();
// ~foo.num
~num.toNumber();
ArkTS1.2对js对象进行二元运算
规则: arkts-interop-js2s-binary-op
级别: error
ArkTS1.1
// file1.js
export let foo = { a: 1, b: 2 };
// file2.ets
import { foo } from './file1';
let a = foo.a;
let b = foo.b;
a + b;
a - b;
a * b;
a / b;
a % b;
a ** b;
ArkTS1.2
// file1.js
export let foo = { a: 1, b: 2 };
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let a = foo.getProperty('a').toNumber();
let b = foo.getProperty('b').toNumber();
a + b;
a - b;
a * b;
a / b;
a % b;
a ** b;
ArkTS1.2 await js Promise对象
规则: arkts-interop-js2s-await-js-promise
级别: error
ArkTS1.1
// file1.js
async function foo(){}
export let p = foo()
// file2.ets
import {p} from "./file1"
async function bar() {
await p.toPromise();
}
ArkTS1.2
// file1.js
async function foo(){}
export let p = foo()
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1')
let p = mod.getProperty('p')
async function bar() {
await p.toPromise();
}
ArkTS1.2对js数据进行比较
规则: arkts-interop-js2s-compare-js-data
级别: error
ArkTS1.1
// file1.js
export let foo = { a: 1, b: 2 };
// file2.ets
import { foo } from './file1';
let a = foo.a;
let b = foo.b;
a > b;
a < b;
a >= b;
a <= b;
ArkTS1.2
// file1.js
export let a = 1;
export let b = 2;
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let a = foo.getProperty('a').toNumber();
let b = foo.getProperty('b').toNumber();
a > b;
a < b;
a >= b;
a <= b;
ArkTS1.2对js数据进行相等判断
规则: arkts-interop-js2s-equality-judgment
级别: error
ArkTS1.1
// file1.js
class A {}
export let a = new A();
export let b = new A();
// file2.ets
import { a, b } from './file1';
a == b;
a != b;
a === b;
a !== b;
ArkTS1.2
// file1.js
class A {}
export let a = new A();
export let b = new A();
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let a = mod.getProperty('a');
let b = mod.getProperty('b');
a.isEqualTo(b);
!a.isEqualTo(b);
a.isStrictlyEqualTo(b);
!a.isStrictlyEqualTo(b);
ArkTS1.2对js对象进行条件判断
规则: arkts-interop-js2s-condition-judgment
级别: error
ArkTS1.1
// file1.js
export let foo = { isGood: true };
// file2.ets
import { foo } from './file1';
if (foo.isGood) {}
ArkTS1.2
// file1.js
export let foo = { isGood: true };
// file2.ets
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let isGood = foo.getProperty('isGood').toBoolean();
if (isGood) {}
ArkTS1.2继承js的类
规则: arkts-interop-js2s-inherit-js-class
级别: error
ArkTS1.1
// file1.js
export class A {}
// file2.ets
import { A } from './file1';
class B extends A {}
let b = new B();
ArkTS1.2
// file1.js
export class A {}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let A = mod.getProperty('A');
let fixArr: FixedArray<ESValue> = [];
let esvalueCB = (argThis: ESValue, argNewTgt: ESValue, args: FixedArray<ESValue>, data?: ESValueCallbackData) => {
return ESValue.Undefined;
};
let B: ESValue = ESValue.defineClass('B', esvalueCB, undefined, undefined, A);
let b = B.instantiate();
ArkTS1.2处理js非常规异常
规则: arkts-interop-js2s-js-exception
级别: error
ArkTS1.1
// file1.js
export function foo() {
throw 123;
}
// file2.ets
import { foo } from './file1';
try {
foo();
} catch (e) {
console.log("result is " + (e as number)); //123
}
ArkTS1.2
// file1.js
export function foo() {
throw 123;
}
// file2.ets
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
try {
foo.invoke();
} catch (e) {
let err: ESValue = (e as ESError).getValue();
err.toNumber(); // 123
}
ArkTS1.2访问js的boxed对象
规则: arkts-interop-js2s-boxed-type
级别: error
ArkTS1.1
// file1.js
export let foo = {
num: new Number(123),
bool: new Boolean(true),
str: new String('hello'),
};
// file2.ets
import { foo } from './file1';
typeof foo.num; // 'object'
typeof foo.bool; // 'object'
typeof foo.str; // 'object'
ArkTS1.2
// file1.js
export let foo = {
num: new Number(123),
bool: new Boolean(true),
str: new String('hello'),
};
// file2.ets
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
foo.getProperty('num').typeOf(); // 'number'
foo.getProperty('bool').typeOf(); // 'boolean'
foo.getProperty('str').typeOf(); // 'string'
ArkTS1.2遍历js对象
规则: arkts-interop-js2s-traverse-js-instance
级别: error
ArkTS1.1
// file1.js
export let foo = { arr: [1, 2, 3] };
// file2.ets
import { foo } from './file1';
let arr = foo.arr;
let len = arr.length as number;
for (let i = 0; i < len; ++i) {
arr[i] as number;
arr[i] = 0;
}
ArkTS1.2
// file1.js
export let foo = { arr: [1, 2, 3] };
// file2.ets ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
let arr = foo.getProerpty('arr');
let len = arr.getProerpty('length').toNumber();
for (let i = 0; i < len; ++i) {
arr.getProperty(i).toNumber();
arr.setProperty(i, ESValue.wrap(0));
}
js调用ArkTS1.2函数和传参
规则: arkts-interop-js2s-js-call-static-func
级别: error
ArkTS1.1
// file1.js
export function handle(cb) {
let p = { name: 'hello' };
cb(p);
}
// file2.ets
import { handle } from './file1';
interface Person {
name: string;
}
function foo(p: Person) {}
let lambda = (p: Person) => {};
handle(foo);
handle(lambda);
ArkTS1.2
// file1.js
export function handle(cb) {
let p = { name: 'hello' };
cb(p);
}
// file2.ets
'use static'
let mod = ESValue.load('./file1');
let handle = mod.getProperty('handle');
interface Person {
name: string;
}
function foo(p: Person) {}
// solution: function foo(p: ESValue) {}
let lambda = (p: Person) => {};
// solution: let lambda = (p: ESValue) => {}
handle.invoke(ESValue.wrap(foo));
handle.invoke(ESValue.wrap(lambda));
js增删改ArkTS1.2对象属性
规则: arkts-interop-js2s-js-add-delete-static-prop
级别: error
ArkTS1.1
// file1.js
export function foo(obj) {
obj.newField = 1; // 增加属性
delete obj.data; // 删除属性
obj.name = '123'; // 修改属性值(同类型)
obj.name = { firstName: '456' }; // 修改属性值(不同类型)
}
// file2.ets
import { foo } from './file1';
class X {
name: string = '';
data: number = 0;
}
foo(new X());
ArkTS1.2
// file1.js
export function foo(obj) {
obj.newField = 1; // 增加属性 运行时报错
delete obj.data; // 删除属性 运行时报错
obj.name = '123'; // 修改属性值(同类型)OK
obj.name = { firstName: '456' }; // 修改属性值(不同类型)运行时报错
}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
class X {
name: string = '';
data: number = 0;
}
foo.invoke(ESValue.wrap(new X()));
js Object内置方法作用在ArkTS1.2对象
规则: arkts-interop-js2s-js-object-on-static-instance
级别: error
ArkTS1.1
// file1.js
export function foo(prx) {
Object.getOwnPropertyNames(prx); // ["a"]
Object.hasOwn(prx, 'a'); // true
Object.keys(prx); // ["a"]
Object.values(prx); // [1]
}
// file2.ets
import { foo } from './file1';
class X {
a = 1;
}
foo(new X());
ArkTS1.2
// file1.js
export function foo(prx) {
Object.getOwnPropertyNames(prx) // []
Object.hasOwn(prx, "a") // false
Object.keys(prx) // []
Object.values(prx) // []
}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1')
let foo = mod.getProperty('foo')
class X { a = 1 }
foo.invoke(ESValue.wrap(new X()))
js Reflect内置方法作用在ArkTS1.2对象
规则: arkts-interop-js2s-js-reflect-on-static-instance
级别: error
ArkTS1.1
// file1.js
export function foo(prx) {
Reflect.ownKeys(prx); // ['a']
Reflect.set(prx, 'newField', 7); // true
}
// file2.ets
import { foo } from './file1';
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo(new X());
ArkTS1.2
// file1.js
export function foo(prx) {
Reflect.ownKeys(prx); // []
Reflect.set(prx, 'newField', 7); // false
}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1');
let foo = mod.getProperty('foo');
class X {
a: string = 'hello';
getName() {
return this.a;
}
}
foo.invoke(ESValue.wrap(new X()));
js对ArkTS1.2对象进行展开语法
规则: arkts-interop-js2s-js-expand-static-instance
级别: error
ArkTS1.1
// file1.js
export function foo(obj) {
let x = {...obj} // x会是{ a = 1; b = 2; c = 3 }
let {a, b, ...rest} = obj // a会是1, b会是2, rest会是{c: 3}
// file2.ets
import {foo} from "./file1"
class X { a = 1; b = 2; c = 3 }
foo(new X())
// class interface Record
ArkTS1.2
// file1.js
export function foo(obj) {
let x = {...obj} // x会是空对象{},因为静态对象没有自有属性
// 解决方案:let x = {a: obj.a, b: obj.b, c: obj.c}
// 或者使用keys + Reflect.get
let {a, b, ...rest} = obj // a会是1,b会是2,rest会是空对象{},因为静态对象没有自有属性
// 解决方案: let rest = {c: obj.c}
// file2.ets // ArkTS1.2
'use static'
let mod = ESValue.load('./file1')
let foo = mod.getProperty('foo')
class X { a = 1; b = 2; c = 3 }
foo.invoke(ESValue.wrap(new X()))
ArkTS1.2动态导入JS
规则: arkts-interop-js2s-dynamic-import-js
级别: error
ArkTS1.1
// file1.js
export class A {}
// file2.ets ArkTS1.1
let mod: ESObject = await import('./file1')
let A: ESObject = mod.A
new A()
ArkTS1.2
// file1.js
export class A {}
// file2.ets ArkTS1.2
'use static'
let mod: ESValue = ESValue.load('./file1')
let A: ESValue = mod.getProperty('A')
A.instantiate()