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回答
- 3粉丝
- 0关注
- 11-从TypeScript到ArkTS的适配规则(1)
- 13-从TypeScript到ArkTS的适配规则(3)
- 14-从TypeScript到ArkTS的适配规则(4)
- 15-从 TypeScript 到 ArkTS 的适配规则(5)
- 16-从 TypeScript 到 ArkTS 的适配规则(6)
- 鸿蒙Flutter实战:12-使用模拟器开发调试
- 08-ArkTS 语法入门(2)
- 从零到智能:打造智能灯控应用
- 从0到1上架一个元服务的全流程
- 「Mac畅玩鸿蒙与硬件12」鸿蒙UI组件篇2 - Image组件的使用
- 如何完成挖孔屏的适配
- HarmonyOS ArkTS中视频播放Video组件实现竖屏到横屏切换
- LazyForEach ArkTS中的性能加速器
- 常用的ArkTS第三方库
- HarmonyOS Next V2 状态管理AppStorageV2和PersistenceV2