12-从TypeScript到ArkTS的适配规则(2)
12-从TypeScript到ArkTS的适配规则(2)
不支持this类型
**规则:**arkts-no-typing-with-this
级别:错误
ArkTS不支持this类型,改用显式具体类型。
TypeScript
interface ListItem {  getHead(): this}
class C {  n: number = 0
  m(c: this) {    // ...  }}
ArkTS
interface ListItem {  getHead(): ListItem}
class C {  n: number = 0
  m(c: C) {    // ...  }}
不支持条件类型
**规则:**arkts-no-conditional-types
级别:错误
ArkTS不支持条件类型别名,引入带显式约束的新类型,或使用Object重写逻辑。
不支持infer关键字。
TypeScript
type X<T> = T extends number ? T: nevertype Y<T> = T extends Array<infer Item> ? Item: never
ArkTS
// 在类型别名中提供显式约束type X1<T extends number> = T
// 用Object重写,类型控制较少,需要更多的类型检查以确保安全type X2<T> = Object
// Item必须作为泛型参数使用,并能正确实例化type YI<Item, T extends Array<Item>> = Item
不支持在constructor中声明字段
**规则:**arkts-no-ctor-prop-decls
级别:错误
ArkTS不支持在constructor中声明类字段。在class中声明这些字段。
TypeScript
class Person {  constructor(    protected ssn: string,    private firstName: string,    private lastName: string  ) {    this.ssn = ssn;    this.firstName = firstName;    this.lastName = lastName;  }
  getFullName(): string {    return this.firstName + ' ' + this.lastName;  }}
ArkTS
class Person {  protected ssn: string  private firstName: string  private lastName: string
  constructor(ssn: string, firstName: string, lastName: string) {    this.ssn = ssn;    this.firstName = firstName;    this.lastName = lastName;  }
  getFullName(): string {    return this.firstName + ' ' + this.lastName;  }}
接口中不支持构造签名
**规则:**arkts-no-ctor-signatures-iface
级别:错误
ArkTS不支持在接口中使用构造签名。改用函数或者方法。
TypeScript
interface I {  new (s: string): I}
function fn(i: I) {  return new i('hello');}
ArkTS
interface I {  create(s: string): I}
function fn(i: I) {  return i.create('hello');}
不支持索引访问类型
**规则:**arkts-no-aliases-by-index
级别:错误
ArkTS不支持索引访问类型。
不支持通过索引访问字段
**规则:**arkts-no-props-by-index
级别:错误
ArkTS不支持动态声明字段,不支持动态访问字段。只能访问已在类中声明或者继承可见的字段,访问其他字段将会造成编译时错误。
使用点操作符访问字段,例如(obj.field),不支持索引访问(obj[field])。
ArkTS支持通过索引访问TypedArray(例如Int32Array)中的元素。
TypeScript
class Point {  x: string = ''  y: string = ''}let p: Point = {x: '1', y: '2'};console.log(p['x']);
class Person {  name: string = ''  age: number = 0;  [key: string]: string | number}
let person: Person = {  name: 'John',  age: 30,  email: '***@example.com',  phoneNumber: '18*********',}
ArkTS
class Point {  x: string = ''  y: string = ''}let p: Point = {x: '1', y: '2'};console.log(p.x);
class Person {  name: string  age: number  email: string  phoneNumber: string
  constructor(name: string, age: number, email: string,        phoneNumber: string) {    this.name = name;    this.age = age;    this.email = email;    this.phoneNumber = phoneNumber;  }}
let person = new Person('John', 30, '***@example.com', '18*********');console.log(person['name']);     // 编译时错误console.log(person.unknownProperty); // 编译时错误
let arr = new Int32Array(1);arr[0];
不支持structural typing
**规则:**arkts-no-structural-typing
级别:错误
ArkTS不支持structural typing,编译器无法比较两种类型的publicAPI并决定它们是否相同。使用其他机制,例如继承、接口或类型别名。
TypeScript
interface I1 {  f(): string}
interface I2 { // I2等价于I1  f(): string}
class X {  n: number = 0  s: string = ''}
class Y { // Y等价于X  n: number = 0  s: string = ''}
let x = new X();let y = new Y();
console.log('Assign X to Y');y = x;
console.log('Assign Y to X');x = y;
function foo(x: X) {  console.log(x.n + x.s);}
// 由于X和Y的API是等价的,所以X和Y是等价的foo(new X());foo(new Y());
ArkTS
interface I1 {  f(): string}
type I2 = I1 // I2是I1的别名
class B {  n: number = 0  s: string = ''}
// D是B的继承类,构建了子类型和父类型的关系class D extends B {  constructor() {    super()  }}
let b = new B();let d = new D();
console.log('Assign D to B');b = d; // 合法赋值,因为B是D的父类
// 将b赋值给d将会引起编译时错误// d = b
interface Z {   n: number   s: string}
// 类X implements 接口Z,构建了X和Y的关系class X implements Z {  n: number = 0  s: string = ''}
// 类Y implements 接口Z,构建了X和Y的关系class Y implements Z {  n: number = 0  s: string = ''}
let x: Z = new X();let y: Z = new Y();
console.log('Assign X to Y');y = x // 合法赋值,它们是相同的类型
console.log('Assign Y to X');x = y // 合法赋值,它们是相同的类型
function foo(c: Z): void {  console.log(c.n + c.s);}
// 类X和类Y implement 相同的接口,因此下面的两个函数调用都是合法的foo(new X());foo(new Y());
需要显式标注泛型函数类型实参
**规则:**arkts-no-inferred-generic-params
级别:错误
如果可以从传递给泛型函数的参数中推断出具体类型,ArkTS允许省略泛型类型实参。否则,省略泛型类型实参会发生编译时错误。
禁止仅基于泛型函数返回类型推断泛型类型参数。
TypeScript
function choose<T>(x: T, y: T): T {  return Math.random() < 0.5 ? x: y;}
let x = choose(10, 20);   // 推断choose<number>(...)let y = choose('10', 20); // 编译时错误
function greet<T>(): T {  return 'Hello' as T;}let z = greet() // T的类型被推断为“unknown”
ArkTS
function choose<T>(x: T, y: T): T {  return Math.random() < 0.5 ? x: y;}
let x = choose(10, 20);   // 推断choose<number>(...)let y = choose('10', 20); // 编译时错误
function greet<T>(): T {  return 'Hello' as T;}let z = greet<string>();
需要显式标注对象字面量的类型
**规则:**arkts-no-untyped-obj-literals
级别:错误
在ArkTS中,需要显式标注对象字面量的类型,否则,将发生编译时错误。在某些场景下,编译器可以根据上下文推断出字面量的类型。
在以下上下文中不支持使用字面量初始化类和接口:
- 初始化具有any、Object或object类型的任何对象
- 初始化带有方法的类或接口
- 初始化包含自定义含参数的构造函数的类
- 初始化带readonly字段的类
例子1
TypeScript
let o1 = {n: 42, s: 'foo'};let o2: Object = {n: 42, s: 'foo'};let o3: object = {n: 42, s: 'foo'};
let oo: Object[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];
ArkTS
class C1 {  n: number = 0  s: string = ''}
let o1: C1 = {n: 42, s: 'foo'};let o2: C1 = {n: 42, s: 'foo'};let o3: C1 = {n: 42, s: 'foo'};
let oo: C1[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];
例子2
TypeScript
class C2 {  s: string  constructor(s: string) {    this.s = 's =' + s;  }}let o4: C2 = {s: 'foo'};
ArkTS
class C2 {  s: string  constructor(s: string) {    this.s = 's =' + s;  }}let o4 = new C2('foo');
例子3
TypeScript
class C3 {  readonly n: number = 0  readonly s: string = ''}let o5: C3 = {n: 42, s: 'foo'};
ArkTS
class C3 {  n: number = 0  s: string = ''}let o5: C3 = {n: 42, s: 'foo'};
例子4
TypeScript
abstract class A {}let o6: A = {};
ArkTS
abstract class A {}class C extends A {}let o6: C = {}; // 或 let o6: C = new C()
例子5
TypeScript
class C4 {  n: number = 0  s: string = ''  f() {    console.log('Hello');  }}let o7: C4 = {n: 42, s: 'foo', f: () => {}};
ArkTS
class C4 {  n: number = 0  s: string = ''  f() {    console.log('Hello');  }}let o7 = new C4();o7.n = 42;o7.s = 'foo';
例子6
TypeScript
class Point {  x: number = 0  y: number = 0}
function getPoint(o: Point): Point {  return o;}
// TS支持structural typing,可以推断p的类型为Pointlet p = {x: 5, y: 10};getPoint(p);
// 可通过上下文推断出对象字面量的类型为PointgetPoint({x: 5, y: 10});
ArkTS
class Point {  x: number = 0  y: number = 0
  // 在字面量初始化之前,使用constructor()创建一个有效对象。  // 由于没有为Point定义构造函数,编译器将自动添加一个默认构造函数。}
function getPoint(o: Point): Point {  return o;}
// 字面量初始化需要显式定义类型let p: Point = {x: 5, y: 10};getPoint(p);
// getPoint接受Point类型,字面量初始化生成一个Point的新实例getPoint({x: 5, y: 10});
对象字面量不能用于类型声明
**规则:**arkts-no-obj-literals-as-types
级别:错误
ArkTS不支持使用对象字面量声明类型,可以使用类或者接口声明类型。
TypeScript
let o: {x: number, y: number} = {  x: 2,  y: 3}
type S = Set<{x: number, y: number}>
ArkTS
class O {  x: number = 0  y: number = 0}
let o: O = {x: 2, y: 3};
type S = Set<O>
数组字面量必须仅包含可推断类型的元素
**规则:**arkts-no-noninferrable-arr-literals
级别:错误
本质上,ArkTS将数组字面量的类型推断为数组所有元素的联合类型。如果其中任何一个元素的类型无法根据上下文推导出来(例如,无类型的对象字面量),则会发生编译时错误。
TypeScript
let a = [{n: 1, s: '1'}, {n: 2, s: '2'}];
ArkTS
class C {  n: number = 0  s: string = ''}
let a1 = [{n: 1, s: '1'} as C, {n: 2, s: '2'} as C]; // a1的类型为“C[]”let a2: C[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];    // a2的类型为“C[]”
使用箭头函数而非函数表达式
**规则:**arkts-no-func-expressions
级别:错误
ArkTS不支持函数表达式,使用箭头函数。
TypeScript
let f = function (s: string) {  console.log(s);}
ArkTS
let f = (s: string) => {  console.log(s);}
不支持使用类表达式
**规则:**arkts-no-class-literals
级别:错误
ArkTS不支持使用类表达式,必须显式声明一个类。
TypeScript
const Rectangle = class {  constructor(height: number, width: number) {    this.height = height;    this.width = width;  }
  height  width}
const rectangle = new Rectangle(0.0, 0.0);
ArkTS
class Rectangle {  constructor(height: number, width: number) {    this.height = height;    this.width = width;  }
  height: number  width: number}
const rectangle = new Rectangle(0.0, 0.0);
类不允许implements
**规则:**arkts-implements-only-iface
级别:错误
ArkTS不允许类被implements,只有接口可以被implements。
TypeScript
class C {  foo() {}}
class C1 implements C {  foo() {}}
ArkTS
interface C {  foo(): void}
class C1 implements C {  foo() {}}
不支持修改对象的方法
**规则:**arkts-no-method-reassignment
级别:错误
ArkTS不支持修改对象的方法。在静态语言中,对象的布局是确定的。一个类的所有对象实例享有同一个方法。
如果需要为某个特定的对象增加方法,可以封装函数或者使用继承的机制。
TypeScript
class C {  foo() {    console.log('foo');  }}
function bar() {  console.log('bar');}
let c1 = new C();let c2 = new C();c2.foo = bar;
c1.foo(); // fooc2.foo(); // bar
ArkTS
class C {  foo() {    console.log('foo');  }}
class Derived extends C {  foo() {    console.log('Extra');    super.foo();  }}
function bar() {  console.log('bar');}
let c1 = new C();let c2 = new C();c1.foo(); // fooc2.foo(); // foo
let c3 = new Derived();c3.foo(); // Extra foo
- 0回答
- 6粉丝
- 1关注
- 11-从TypeScript到ArkTS的适配规则(1)
- 13-从TypeScript到ArkTS的适配规则(3)
- 14-从TypeScript到ArkTS的适配规则(4)
- 15-从 TypeScript 到 ArkTS 的适配规则(5)
- 16-从 TypeScript 到 ArkTS 的适配规则(6)
- 从零到一:flutter_timezone库的鸿蒙适配深度探索
- 鸿蒙Flutter实战:12-使用模拟器开发调试
- FlutterToast 三方库鸿蒙适配之旅:从零到一的深度实践
- 掌握未来:从入门到精通OpenKyLin探索之旅(2)
- Flutter_udid 三方库鸿蒙适配之旅:从零到一的深度实践
- flutter_exit_app 三方库鸿蒙适配之旅:从零到一的深度实践
- 打造鸿蒙三方库生态新基石:从适配共建到生态繁荣
- API9 到 API12,有哪些不同
- Flutter到鸿蒙的跨越:torch_light库的鸿蒙适配之旅
- (七)ArkCompiler 的编译流程:从源码到字节码的深度解析

