12-从TypeScript到ArkTS的适配规则(2)

2024-12-12 21:16:41
126次阅读
0个评论

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
收藏00

登录 后评论。没有帐号? 注册 一个。