從TypeScript到ArkTS的遷移指導(dǎo)
本文通過提供簡潔的約束指導(dǎo)如何將標(biāo)準(zhǔn)的TypeScript代碼重構(gòu)為ArkTS代碼,。盡管ArkTS是基于TypeScript設(shè)計(jì)的,但出于性能考慮,一些TypeScript的特性被限制了。因此,在ArkTS中,所有的TypeScript特性被分成三類,。
完全支持的特性 :原始代碼無需任何修改,。根據(jù)測試,對于已遵循最佳TypeScript實(shí)踐的項(xiàng)目,代碼庫中90%到97%的內(nèi)容可以保持原封不動(dòng)。部分支持的特性 :需小規(guī)模的代碼重構(gòu),。例如,必須使用關(guān)鍵字let
代替var
來聲明變量,。不支持的特性 :需大規(guī)模的代碼重構(gòu)。例如,不支持any
類型,所有使用any
的代碼都需要引入顯式類型,。
本文將逐一介紹所有部分支持和所有不支持的特性,并提供代碼重構(gòu)的建議,。根據(jù)本文提供的約束進(jìn)行代碼重構(gòu)后代碼仍為有效的TypeScript代碼。對于沒有提到的特性,則說明ArkTS完全支持,。
示例
包含關(guān)鍵字var
的原始TypeScript代碼:
function addTen ( x: number ) : number {
var ten = 10
return x + ten
}
重構(gòu)后的代碼:
// 重要!重構(gòu)后仍然是有效的TypeScript代碼,。
function addTen ( x: number ) : number {
let ten = 10
return x + ten
}
不支持的特性
目前,不支持的特性主要包括:
與降低運(yùn)行時(shí)性能的動(dòng)態(tài)類型相關(guān)的特性。 需要編譯器額外支持從而導(dǎo)致項(xiàng)目構(gòu)建時(shí)間增加的特性,。
根據(jù)開發(fā)者的反饋以及更多實(shí)際場景的數(shù)據(jù),我們將來可能進(jìn)一步縮小 不支持特性的范圍,。
概述
本節(jié)羅列了ArkTS不支持或部分支持的TypeScript特性,。完整的列表以及詳細(xì)的代碼示例和重構(gòu)建議,請參考。
強(qiáng)制使用靜態(tài)類型
ArkTS在設(shè)計(jì)之初,就確定了如下目標(biāo):
ArkTS代碼需非常容易閱讀和理解,因?yàn)榇a的閱讀頻率高于編寫頻率,。 以最小功耗快速執(zhí)行代碼,這點(diǎn)對于移動(dòng)設(shè)備(ArkTS的目標(biāo)設(shè)備)來說至關(guān)重要,。
靜態(tài)類型是ArkTS最重要的特性之一。使用靜態(tài)類型有助于實(shí)現(xiàn)上述兩個(gè)目標(biāo),。如果程序采用靜態(tài)類型,即所有類型在編譯時(shí)都是已知的,那么開發(fā)者就能夠容易理解代碼中使用了哪些數(shù)據(jù)結(jié)構(gòu),。同時(shí),由于所有類型在程序?qū)嶋H運(yùn)行前都是已知的,編譯器可以提前驗(yàn)證代碼的正確性,從而可以減少運(yùn)行時(shí)的類型檢查,有助于性能提升。
基于上述考慮,ArkTS中禁止使用any
類型,。
示例
//
// 不支持:
//
let res : any = some_api_function ( "hello" , "world" )
// `res`是什么?錯(cuò)誤代碼的數(shù)字?字符串?對象?
// 該如何處理它?
//
// 支持:
//
class CallResult {
public succeeded ( ) : boolean { ... }
public errorMessage ( ) : string { ... }
}
let res : CallResult = some_api_function ( "hello" , "world" )
if ( ! res. succeeded ( ) ) {
console . log ( "Call failed: " + res. errorMessage ( ) )
}
any
類型在TypeScript中并不常見,只有大約1%的TypeScript代碼庫使用,。一些代碼檢查工具(例如ESLint)也制定一系列規(guī)則來禁止使用any
。因此,雖然禁止any
將導(dǎo)致代碼重構(gòu),但重構(gòu)量很小,有助于整體性能提升,因此這個(gè)約束是非常有價(jià)值的,。
禁止在運(yùn)行時(shí)變更對象布局
為實(shí)現(xiàn)最佳性能,ArkTS要求在程序執(zhí)行期間不能更改對象的布局,。換句話說,ArkTS禁止以下行為:
向?qū)ο笾刑砑有碌膶傩曰蚍椒?/li> 從對象中刪除已有的屬性或方法 將任意類型的值賦值給對象屬性
TypeScript編譯器已經(jīng)禁止了許多此類操作。然而,有些操作還是有可能繞過編譯器的,例如,使用ArkTS不支持的as any
進(jìn)行轉(zhuǎn)換,。(詳見下面的示例,。)
示例
class Point {
public x : number = 0
public y : number = 0
constructor ( x : number , y : number ) {
this . x = x
this . y = y
}
}
// 無法從對象中刪除某個(gè)屬性,從而確保所有Point對象都具有屬性x:
let p1 = new Point ( 1.0 , 1.0 )
delete p1. x // 在TypeScript和ArkTS中,都會產(chǎn)生編譯時(shí)錯(cuò)誤
delete ( p1 as any ) . x // 在TypeScript中不會報(bào)錯(cuò);在ArkTS中會產(chǎn)生編譯時(shí)錯(cuò)誤
// Point類沒有定義命名為z的屬性,在程序運(yùn)行時(shí)也無法添加該屬性:
let p2 = new Point ( 2.0 , 2.0 )
p2. z = "Label" ; // 在TypeScript和ArkTS中,都會產(chǎn)生編譯時(shí)錯(cuò)誤
( p2 as any ) . z = "Label" // 在TypeScript中不會報(bào)錯(cuò);在ArkTS中會產(chǎn)生編譯時(shí)錯(cuò)誤
// 類的定義確保了所有Point對象只有屬性x和y,并且無法被添加其他屬性:
let p3 = new Point ( 3.0 , 3.0 )
let prop = Symbol ( ) ; // 在TypeScript中不會報(bào)錯(cuò);在ArkTS中會產(chǎn)生編譯時(shí)錯(cuò)誤
( p3 as any ) [ prop] = p3. x // 在TypeScript中不會報(bào)錯(cuò);在ArkTS中會產(chǎn)生編譯時(shí)錯(cuò)誤
p3[ prop] = p3. x // 在TypeScript和ArkTS中,都會產(chǎn)生編譯時(shí)錯(cuò)誤
// 類的定義確保了所有Point對象的屬性x和y都具有number類型,因此,無法將其他類型的值賦值給它們:
let p4 = new Point ( 4.0 , 4.0 )
p4. x = "Hello!" ; // 在TypeScript和ArkTS中,都會產(chǎn)生編譯時(shí)錯(cuò)誤
( p4 as any ) . x = "Hello!" // 在TypeScript中不會報(bào)錯(cuò);在ArkTS中會產(chǎn)生編譯時(shí)錯(cuò)誤
// 使用符合類定義的Point對象:
function distance ( p1 : Point, p2 : Point) : number {
return Math. sqrt (
( p2. x - p1. x) * ( p2. x - p1. x) + ( p2. y - p1. y) * ( p2. y - p1. y)
)
}
let p5 = new Point ( 5.0 , 5.0 )
let p6 = new Point ( 6.0 , 6.0 )
console . log ( "Distance between p5 and p6: " + distance ( p5, p6) )
修改對象布局會影響代碼的可讀性以及運(yùn)行時(shí)性能。從開發(fā)者的角度來說,在某處定義類,然后又在其他地方修改實(shí)際的對象布局,很容易引起困惑乃至引入錯(cuò)誤,。此外,這點(diǎn)還需要額外的運(yùn)行時(shí)支持,增加了執(zhí)行開銷,。這一點(diǎn)與靜態(tài)類型的約束也沖突:既然已決定使用顯式類型,為什么還需要添加或刪除屬性呢?
當(dāng)前,只有少數(shù)項(xiàng)目允許在運(yùn)行時(shí)變更對象布局,一些常用的代碼檢查工具也增加了相應(yīng)的限制規(guī)則。這個(gè)約束只會導(dǎo)致少量代碼重構(gòu),但對性能提升會有積極的影響,。
限制運(yùn)算符的語義
為獲得更好的性能并鼓勵(lì)開發(fā)者編寫更清晰的代碼,ArkTS限制了一些運(yùn)算符的語義,。詳細(xì)的語義限制,請參考。
示例
// 一元運(yùn)算符`+`只能作用于數(shù)值類型:
console . log ( + 42 ) // 合法運(yùn)算
console . log ( + "42" ) // 編譯時(shí)錯(cuò)誤
使用額外的語義重載語言運(yùn)算符會增加語言規(guī)范的復(fù)雜度,而且,開發(fā)者還被迫牢記所有可能的例外情況及對應(yīng)的處理規(guī)則,。在某些情況下,產(chǎn)生一些不必要的運(yùn)行時(shí)開銷,。
當(dāng)前只有不到1%的代碼庫使用該特性。因此,盡管限制運(yùn)算符的語義需要重構(gòu)代碼,但重構(gòu)量很小且非常容易操作,并且,通過重構(gòu)能使代碼更清晰,、具備更高性能,。
不支持 structural typing
假設(shè)兩個(gè)不相關(guān)的類T
和U
擁有相同的public
API:
class T {
public name : string = ""
public greet ( ) : void {
console . log ( "Hello, " + this . name)
}
}
class U {
public name : string = ""
public greet ( ) : void {
console . log ( "Greetings, " + this . name)
}
}
我們能把類型為T
的值賦給類型為U
的變量嗎?
let u : U = new T ( ) // 是否允許?
我們能把類型為T
的值傳遞給接受類型為U
的參數(shù)的函數(shù)嗎?
function greeter ( u : U ) {
console . log ( "To " + u. name)
u. greet ( )
}
let t : T = new T ( )
greeter ( t) // 是否允許?
換句話說,我們將采取下面哪種方法呢:
T
和U
沒有繼承關(guān)系或沒有implements
相同的接口,但由于它們具有相同的public
API,它們“在某種程度上是相等的”,所以上述兩個(gè)問題的答案都是“是”;T
和U
沒有繼承關(guān)系或沒有implements
相同的接口,應(yīng)當(dāng)始終被視為完全不同的類型,因此上述兩個(gè)問題的答案都是“否”,。
采用第一種方法的語言支持structural typing,而采用第二種方法的語言則不支持structural typing,。目前TypeScript支持structural typing,而ArkTS不支持。
structural typing是否有助于生成清晰,、易理解的代碼,關(guān)于這一點(diǎn)并沒有定論,。但至少有一點(diǎn)很明確,structural typing不會降低程序的性能(至少在某些時(shí)候)。那為什么ArkTS不支持structural typing呢?
因?yàn)閷tructural typing的支持是一個(gè)重大的特性,需要在語言規(guī)范,、編譯器和運(yùn)行時(shí)進(jìn)行大量的考慮和仔細(xì)的實(shí)現(xiàn),。另外,安全高效的實(shí)現(xiàn)還要考慮到其他方面(靜態(tài)類型、更改對象布局的限制),。鑒于此,當(dāng)前我們還不支持該特性,。根據(jù)實(shí)際場景的需求和反饋,我們后續(xù)會重新加以考慮,。更多案例和建議請參考。
約束說明
對象的屬性名必須是合法的標(biāo)識符
規(guī)則: arkts-identifiers-as-prop-names
級別:錯(cuò)誤
在ArkTS中,對象的屬性名不能為數(shù)字或字符串,。通過屬性名訪問類的屬性,通過數(shù)值索引訪問數(shù)組元素,。
TypeScript
var x = { "name" : 1 , 2 : 3 }
console . log ( x[ "name" ] )
console . log ( x[ 2 ] )
ArkTS
class X {
public name: number = 0
}
let x: X = { name: 1 }
console . log ( x. name)
let y = [ 1 , 2 , 3 ]
console . log ( y[ 2 ] )
// 在需要通過非標(biāo)識符(即不同類型的key)獲取數(shù)據(jù)的場景中,使用Map<Object, some_type>:
let z = new Map< Object, number > ( )
z. set ( "name" , 1 )
z. set ( 2 , 2 )
console . log ( z. get ( "name" ) )
console . log ( z. get ( 2 ) )
相關(guān)約束
不支持Symbol() API 不支持通過索引訪問字段 不支持delete運(yùn)算符 僅允許在表達(dá)式中使用typeof運(yùn)算符 不支持in運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性 限制使用標(biāo)準(zhǔn)庫
不支持Symbol()
API
規(guī)則: arkts-no-symbol
級別:錯(cuò)誤
TypeScript中的Symbol()
API用于在運(yùn)行時(shí)生成唯一的屬性名稱。由于該API的常見使用場景在靜態(tài)類型語言中沒有意義,因此,ArkTS不支持Symbol()
API,。在ArkTS中,對象布局在編譯時(shí)就確定了,且不能在運(yùn)行時(shí)被更改,。
ArkTS也不支持Symbol.iterator
和Iterable interface
。請使用數(shù)組或容器,。
TypeScript
const sym = Symbol ( )
let o = {
[ sym] : "value"
}
let obj = {
data: [ 'a' , 'b' , 'c' ] ,
[ Symbol. iterator] ( ) {
const this_ = this
let index = 0
return {
next ( ) {
return {
done: index >= this_. data. length,
value: 'name_' + this_. data[ index++ ]
}
}
}
}
}
for ( let t of obj) {
console . log ( t)
}
ArkTS
class SomeClass {
public someProperty : string = ""
}
let o = new SomeClass ( )
let arr: string [ ] = [ 'a' , 'b' , 'c' ]
for ( let t of arr) {
console . log ( 'name_' + t)
}
相關(guān)約束
僅支持屬性名為標(biāo)識符的對象 不支持通過索引訪問字段 不支持delete運(yùn)算符 僅允許在表達(dá)式中使用typeof運(yùn)算符 不支持in運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性 限制使用標(biāo)準(zhǔn)庫
不支持以#
開頭的私有字段
規(guī)則: arkts-no-private-identifiers
級別:錯(cuò)誤
ArkTS不支持使用#
符號開頭聲明的私有字段,。改用private
關(guān)鍵字。
TypeScript
class C {
#foo: number = 42
}
ArkTS
class C {
private foo: number = 42
}
類型,、命名空間的命名必須唯一
規(guī)則: arkts-unique-names
級別:錯(cuò)誤
類型(類,、接口、枚舉),、命名空間的命名必須唯一,且與其他名稱(例如:變量名,、函數(shù)名)不同。
TypeScript
let X : string
type X = number [ ] // 類型的別名與變量同名
ArkTS
let X : string
type T = number [ ] // 為避免名稱沖突,此處不允許使用X
使用let
而非var
規(guī)則: arkts-no-var
級別:錯(cuò)誤
ArkTS不支持 var
,請始終使用let
代替,。
TypeScript
function f ( shouldInitialize: boolean ) {
if ( shouldInitialize) {
var x = 10
}
return x
}
console . log ( f ( true ) ) // 10
console . log ( f ( false ) ) // undefined
let upper_let = 0
{
var scoped_var = 0
let scoped_let = 0
upper_let = 5
}
scoped_var = 5 // 可見
scoped_let = 5 // 編譯時(shí)錯(cuò)誤
ArkTS
function f ( shouldInitialize: boolean ) : Object {
let x: Object = new Object ( )
if ( shouldInitialize) {
x = 10
}
return x
}
console . log ( f ( true ) ) // 10
console . log ( f ( false ) ) // {}
let upper_let = 0
let scoped_var = 0
{
let scoped_let = 0
upper_let = 5
}
scoped_var = 5
scoped_let = 5 //編譯時(shí)錯(cuò)誤
使用具體的類型而非any
或unknown
規(guī)則: arkts-no-any-unknown
級別:錯(cuò)誤
ArkTS不支持any
和unknown
類型,。顯式指定具體類型。
TypeScript
let value1 : any
value1 = true
value1 = 42
let value2 : unknown
value2 = true
value2 = 42
ArkTS
let value_b: boolean = true // 或者 let value_b = true
let value_n: number = 42 // 或者 let value_n = 42
let value_o1: Object = true
let value_o2: Object = 42
相關(guān)約束
使用Object[]
而非tuple
規(guī)則: arkts-no-tuples
級別:錯(cuò)誤
當(dāng)前ArkTS不支持tuple,??梢允褂?code>Object[]來代替tuple。
TypeScript
var t: [ number , string ] = [ 3 , "three" ]
var n = t[ 0 ]
var s = t[ 1 ]
ArkTS
let t: Object[ ] = [ 3 , "three" ]
let n = t[ 0 ]
let s = t[ 1 ]
使用class
而非具有call signature的類型
規(guī)則: arkts-no-call-signatures
級別:錯(cuò)誤
ArkTS不支持對象類型中包含call signature,。改用類,。
TypeScript
type DescribableFunction = {
description: string
( someArg: number ) : string // call signature
}
function doSomething ( fn: DescribableFunction) : void {
console . log ( fn. description + " returned " + fn ( 6 ) )
}
ArkTS
class DescribableFunction {
description: string
public invoke ( someArg: number ) : string {
return someArg. toString ( )
}
constructor ( ) {
this . description = "desc"
}
}
function doSomething ( fn: DescribableFunction) : void {
console . log ( fn. description + " returned " + fn. invoke ( 6 ) )
}
doSomething ( new DescribableFunction ( ) )
相關(guān)約束
使用class
而非具有構(gòu)造簽名的類型
規(guī)則: arkts-no-ctor-signatures-type
級別:錯(cuò)誤
ArkTS不支持對象類型中的構(gòu)造簽名。改用類,。
TypeScript
class SomeObject { }
type SomeConstructor = {
new ( s: string ) : SomeObject
}
function fn ( ctor: SomeConstructor) {
return new ctor ( "hello" )
}
ArkTS
class SomeObject {
public f: string
constructor ( s: string ) {
this . f = s
}
}
function fn ( s: string ) : SomeObject {
return new SomeObject ( s)
}
相關(guān)約束
使用class而非具有call signature的類型
僅支持一個(gè)靜態(tài)塊
規(guī)則: arkts-no-multiple-static-blocks
級別:錯(cuò)誤
ArkTS不允許類中有多個(gè)靜態(tài)塊,。如果存在多個(gè)靜態(tài)塊語句,請合并到一個(gè)靜態(tài)塊中。
TypeScript
class C {
static s: string
static {
C . s = "aa"
}
static {
C . s = C . s + "bb"
}
}
ArkTS
class C {
static s: string
static {
C . s = "aa"
C . s = C . s + "bb"
}
}
不支持index signature
規(guī)則: arkts-no-indexed-signatures
級別:錯(cuò)誤
ArkTS不允許index signature,。改用數(shù)組,。
TypeScript
// 帶index signature的接口:
interface StringArray {
[ index: number ] : string
}
function getStringArray ( ) : StringArray {
return [ "a" , "b" , "c" ]
}
const myArray: StringArray = getStringArray ( )
const secondItem = myArray[ 1 ]
ArkTS
class X {
public f: string [ ] = [ ]
}
let myArray: X = new X ( )
const secondItem = myArray. f[ 1 ]
使用繼承而非intersection type
規(guī)則: arkts-no-intersection-types
級別:錯(cuò)誤
目前ArkTS不支持intersection type??梢允褂美^承作為替代方案,。
TypeScript
interface Identity {
id: number
name: string
}
interface Contact {
email: string
phoneNumber: string
}
type Employee = Identity & Contact
ArkTS
interface Identity {
id: number
name: string
}
interface Contact {
email: string
phoneNumber: string
}
interface Employee extends Identity , Contact { }
不支持this
類型
規(guī)則: arkts-no-typing-with-this
級別:錯(cuò)誤
ArkTS不支持this
類型。改用顯式具體類型,。
TypeScript
interface ListItem {
getHead ( ) : this
}
class C {
n: number = 0
m ( c: this ) {
console . log ( c)
}
}
ArkTS
interface ListItem {
getHead ( ) : ListItem
}
class C {
n: number = 0
m ( c: C ) {
console . log ( c)
}
}
不支持條件類型
規(guī)則: arkts-no-conditional-types
級別:錯(cuò)誤
ArkTS不支持條件類型別名,。引入帶顯式約束的新類型,或使用Object
重寫邏輯。不支持infer
關(guān)鍵字。
TypeScript
type X < T > = T extends number ? T : never
type Y < T > = T extends Array < infer Item> ? Item : never
ArkTS
// 在類型別名中提供顯式約束
type X1 < T extends number > = T
// 用Object重寫,這種情況下,類型控制較少,需要更多的類型檢查以確保安全
type X2 < T > = Object
// Item必須作為泛型參數(shù)使用,并能正確實(shí)例化
type YI < Item, T extends Array < Item>> = Item
不支持在constructor
中聲明字段
規(guī)則: arkts-no-ctor-prop-decls
級別:錯(cuò)誤
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
}
}
接口中不支持構(gòu)造簽名
規(guī)則: arkts-no-ctor-signatures-iface
級別:錯(cuò)誤
ArkTS不支持在接口中使用構(gòu)造簽名。改用函數(shù)或者方法,。
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" )
}
相關(guān)約束
不支持索引訪問類型
規(guī)則: arkts-no-aliases-by-index
級別:錯(cuò)誤
ArkTS不支持索引訪問類型,。改用類型別名。
TypeScript
type Point = { x: number , y: number }
type N = Point[ "x" ] // 等同于number
ArkTS
class Point { x: number = 0 ; y: number = 0 }
type N = number
不支持通過索引訪問字段
規(guī)則: arkts-no-props-by-index
級別:錯(cuò)誤
ArkTS不支持動(dòng)態(tài)聲明字段,不支持動(dòng)態(tài)訪問字段,。只能訪問已在類中聲明或者繼承可見的字段,訪問其他字段將會造成編譯時(shí)錯(cuò)誤,。 使用點(diǎn)操作符訪問字段,例如(obj.field
),不支持索引訪問(obj[field]
)。 ArkTS支持通過索引訪問TypedArray
(例如Int32Array
)中的元素,。
TypeScript
class Point {
x: number = 0
y: number = 0
}
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: number = 0
y: number = 0
}
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" ] ) // 編譯時(shí)錯(cuò)誤
console . log ( person. unknownProperty) // 編譯時(shí)錯(cuò)誤
let arr = new Int32Array ( 1 )
console . log ( arr[ 0 ] )
不支持structural typing
規(guī)則: arkts-no-structural-typing
級別:錯(cuò)誤
ArkTS不支持structural typing,編譯器無法比較兩種類型的public
API并決定它們是否相同,。使用其他機(jī)制,例如繼承、接口或類型別名,。
TypeScript
interface I1 {
f ( ) : string
}
interface I2 { // I2等價(jià)于I1
f ( ) : string
}
class X {
n: number = 0
s: string = ""
}
class Y { // Y等價(jià)于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是等價(jià)的,所以X和Y是等價(jià)的
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的繼承類,構(gòu)建了子類型和父類型的關(guān)系
class D extends B {
constructor ( ) {
super ( )
}
}
let b = new B ( )
let d = new D ( )
console . log ( "Assign D to B" )
b = d // 合法賦值,因?yàn)锽是D的父類
// 將b賦值給d將會引起編譯時(shí)錯(cuò)誤
// d = b
interface Z {
n: number
s: string
}
// 類X implements 接口Z,構(gòu)建了X和Y的關(guān)系
class X implements Z {
n: number = 0
s: string = ""
}
// 類Y implements 接口Z,構(gòu)建了X和Y的關(guān)系
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 相同的接口,因此下面的兩個(gè)函數(shù)調(diào)用都是合法的
foo ( new X ( ) )
foo ( new Y ( ) )
需要顯式標(biāo)注泛型函數(shù)類型實(shí)參
規(guī)則: arkts-no-inferred-generic-params
級別:錯(cuò)誤
如果可以從傳遞給泛型函數(shù)的參數(shù)中推斷出具體類型,ArkTS允許省略泛型類型實(shí)參,。否則,省略泛型類型實(shí)參會發(fā)生編譯時(shí)錯(cuò)誤。禁止僅基于泛型函數(shù)返回類型推斷泛型類型參數(shù),。
TypeScript
function choose < T > ( x: T , y: T ) : T {
return Math. random ( ) < 0.5 ? x : y
}
let x = choose ( 10 , 20 ) // OK,推斷choose<number>(...)
let y = choose ( "10" , 20 ) // 編譯時(shí)錯(cuò)誤
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 ) // OK,推斷choose<number>(...)
let y = choose ( "10" , 20 ) // 編譯時(shí)錯(cuò)誤
function greet < T > ( ) : T {
return "Hello" as T
}
let z = greet < string > ( )
不支持使用正則字面量
規(guī)則: arkts-no-regexp-literals
級別:錯(cuò)誤
當(dāng)前ArkTS不支持正則字面量,。請使用RegExp()
創(chuàng)建正則對象。
TypeScript
let regex: RegExp = / bc*d /
ArkTS
let regex: RegExp = new RegExp ( "/bc*d/" )
需要顯式標(biāo)注對象字面量的類型
規(guī)則: arkts-no-untyped-obj-literals
級別:錯(cuò)誤
在ArkTS中,需要顯式標(biāo)注對象字面量的類型,否則,將發(fā)生編譯時(shí)錯(cuò)誤,。在某些場景下,編譯器可以根據(jù)上下文推斷出字面量的類型,。
在以下上下文中不支持使用字面量初始化類和接口:
初始化具有any
、Object
或object
類型的任何對象 初始化帶有方法的類或接口 初始化包含自定義含參數(shù)的構(gòu)造函數(shù)的類 初始化帶readonly
字段的類
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" } ]
class C2 {
s: string
constructor ( s: string ) {
this . s = "s =" + s
}
}
let o4: C2 = { s: "foo" }
class C3 {
readonly n: number = 0
readonly s: string = ""
}
let o5: C3 = { n: 42 , s: "foo" }
abstract class A { }
let o6: A = { }
class C4 {
n: number = 0
s: string = ""
f ( ) {
console . log ( "Hello" )
}
}
let o7: C4 = { n: 42 , s: "foo" , f : ( ) => { } }
class Point {
x: number = 0
y: number = 0
}
function id_x_y ( o: Point) : Point {
return o
}
// TS支持structural typing,可以推斷p的類型為Point
let p = { x: 5 , y: 10 }
id_x_y ( p)
// 可通過上下文推斷出對象字面量的類型為Point
id_x_y ( { x: 5 , y: 10 } )
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" } ]
class C2 {
s: string
constructor ( s: string ) {
this . s = "s =" + s
}
}
let o4 = new C2 ( "foo" )
class C3 {
n: number = 0
s: string = ""
}
let o5: C3 = { n: 42 , s: "foo" }
abstract class A { }
class C extends A { }
let o6: C = { } // 或 let o6: C = new C()
class C4 {
n: number = 0
s: string = ""
f ( ) {
console . log ( "Hello" )
}
}
let o7 = new C4 ( )
o7. n = 42
o7. s = "foo"
class Point {
x: number = 0
y: number = 0
// 在字面量初始化之前,使用constructor()創(chuàng)建一個(gè)有效對象,。
// 由于沒有為Point定義構(gòu)造函數(shù),編譯器將自動(dòng)添加一個(gè)默認(rèn)構(gòu)造函數(shù),。
}
function id_x_y ( o: Point) : Point {
return o
}
// 字面量初始化需要顯式定義類型
let p: Point = { x: 5 , y: 10 }
id_x_y ( p)
// id_x_y接受Point類型,字面量初始化生成一個(gè)Point的新實(shí)例
id_x_y ( { x: 5 , y: 10 } )
相關(guān)約束
對象字面量不能用于類型聲明 數(shù)組字面量必須僅包含可推斷類型的元素
對象字面量不能用于類型聲明
規(guī)則: arkts-no-obj-literals-as-types
級別:錯(cuò)誤
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 >
相關(guān)約束
對象字面量必須對應(yīng)某些顯式聲明的類或接口 數(shù)組字面量必須僅包含可推斷類型的元素
數(shù)組字面量必須僅包含可推斷類型的元素
規(guī)則: arkts-no-noninferrable-arr-literals
級別:錯(cuò)誤
本質(zhì)上,ArkTS將數(shù)組字面量的類型推斷為數(shù)組所有元素的聯(lián)合類型,。如果其中任何一個(gè)元素的類型無法根據(jù)上下文推導(dǎo)出來(例如,無類型的對象字面量),則會發(fā)生編譯時(shí)錯(cuò)誤,。
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[]”
相關(guān)約束
對象字面量必須對應(yīng)某些顯式聲明的類或接口 對象字面量不能用于類型聲明
使用箭頭函數(shù)而非函數(shù)表達(dá)式
規(guī)則: arkts-no-func-expressions
級別:錯(cuò)誤
ArkTS不支持函數(shù)表達(dá)式。使用箭頭函數(shù),。
TypeScript
let f = function ( s: string ) {
console . log ( s)
}
ArkTS
let f = ( s: string ) => {
console . log ( s)
}
使用泛型函數(shù)而非泛型箭頭函數(shù)
規(guī)則: arkts-no-generic-lambdas
級別:錯(cuò)誤
ArkTS不支持泛型箭頭函數(shù),。
TypeScript
let generic_arrow_func = < T extends String > ( x: T ) => { return x }
generic_arrow_func ( "string" )
ArkTS
function generic_func < T extends String> ( x: T ) : T {
return x
}
generic_func < String> ( "string" )
不支持使用類表達(dá)式
規(guī)則: arkts-no-class-literals
級別:錯(cuò)誤
ArkTS不支持使用類表達(dá)式。必須顯式聲明一個(gè)類,。
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
規(guī)則: arkts-implements-only-iface
級別:錯(cuò)誤
ArkTS不允許類被implements
,只有接口可以被implements
,。
TypeScript
class C {
foo ( ) { }
}
class C1 implements C {
foo ( ) { }
}
ArkTS
interface C {
foo ( ) : void
}
class C1 implements C {
foo ( ) { }
}
不支持修改對象的方法
規(guī)則: arkts-no-method-reassignment
級別:錯(cuò)誤
ArkTS不支持修改對象的方法。在靜態(tài)語言中,對象的布局是確定的,。一個(gè)類的所有對象實(shí)例享有同一個(gè)方法,。 如果需要為某個(gè)特定的對象增加方法,可以封裝函數(shù)或者使用繼承的機(jī)制,。
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 ( ) // foo
c2. 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 ( ) // foo
c2. foo ( ) // foo
let c3 = new Derived ( )
c3. foo ( ) // Extra foo
類型轉(zhuǎn)換僅支持as T
語法
規(guī)則: arkts-as-casts
級別:錯(cuò)誤
在ArkTS中,as
關(guān)鍵字是類型轉(zhuǎn)換的唯一語法,。錯(cuò)誤的類型轉(zhuǎn)換會導(dǎo)致編譯時(shí)錯(cuò)誤或者運(yùn)行時(shí)拋出ClassCastException
異常。不支持使用<type>
語法進(jìn)行類型轉(zhuǎn)換。
當(dāng)需要將primitive
類型(如number
或boolean
)轉(zhuǎn)換成引用類型時(shí),請使用new
表達(dá)式,。
TypeScript
class Shape { }
class Circle extends Shape { x: number = 5 }
class Square extends Shape { y: string = "a" }
function createShape ( ) : Shape {
return new Circle ( )
}
let c1 = < Circle> createShape ( )
let c2 = createShape ( ) as Circle
// 如果轉(zhuǎn)換錯(cuò)誤,不會產(chǎn)生編譯時(shí)或運(yùn)行時(shí)報(bào)錯(cuò)
let c3 = createShape ( ) as Square
console . log ( c3. y) // undefined
// 在TS中,由于`as`關(guān)鍵字不會在運(yùn)行時(shí)生效,所以`instanceof`的左操作數(shù)不會在運(yùn)行時(shí)被裝箱成引用類型
let e1 = ( 5.0 as Number) instanceof Number // false
// 創(chuàng)建Number對象,獲得預(yù)期結(jié)果:
let e2 = ( new Number ( 5.0 ) ) instanceof Number // true
ArkTS
class Shape { }
class Circle extends Shape { x: number = 5 }
class Square extends Shape { y: string = "a" }
function createShape ( ) : Shape {
return new Circle ( )
}
let c2 = createShape ( ) as Circle
// 運(yùn)行時(shí)拋出ClassCastException異常:
let c3 = createShape ( ) as Square
// 創(chuàng)建Number對象,獲得預(yù)期結(jié)果:
let e2 = ( new Number ( 5.0 ) ) instanceof Number // true
不支持JSX表達(dá)式
規(guī)則: arkts-no-jsx
級別:錯(cuò)誤
不支持使用JSX,。
一元運(yùn)算符+
、-
和~
僅適用于數(shù)值類型
規(guī)則: arkts-no-polymorphic-unops
級別:錯(cuò)誤
ArkTS僅允許一元運(yùn)算符用于數(shù)值類型,否則會發(fā)生編譯時(shí)錯(cuò)誤,。與TypeScript不同,ArkTS不支持隱式將字符串轉(zhuǎn)換成數(shù)值,必須進(jìn)行顯式轉(zhuǎn)換,。
TypeScript
let a = + 5 // 5(number類型)
let b = + "5" // 5(number類型)
let c = - 5 // -5(number類型)
let d = - "5" // -5(number類型)
let e = ~ 5 // -6(number類型)
let f = ~ "5" // -6(number類型)
let g = + "string" // NaN(number類型)
function returnTen ( ) : string {
return "-10"
}
function returnString ( ) : string {
return "string"
}
let x = + returnTen ( ) // -10(number類型)
let y = + returnString ( ) // NaN
ArkTS
let a = + 5 // 5(number類型)
let b = + "5" // 編譯時(shí)錯(cuò)誤
let c = - 5 // -5(number類型)
let d = - "5" // 編譯時(shí)錯(cuò)誤
let e = ~ 5 // -6(number類型)
let f = ~ "5" // 編譯時(shí)錯(cuò)誤
let g = + "string" // 編譯時(shí)錯(cuò)誤
function returnTen ( ) : string {
return "-10"
}
function returnString ( ) : string {
return "string"
}
let x = + returnTen ( ) // 編譯時(shí)錯(cuò)誤
let y = + returnString ( ) // 編譯時(shí)錯(cuò)誤
不支持delete
運(yùn)算符
規(guī)則: arkts-no-delete
級別:錯(cuò)誤
ArkTS中,對象布局在編譯時(shí)就確定了,且不能在運(yùn)行時(shí)被更改。因此,刪除屬性的操作沒有意義,。
TypeScript
class Point {
x? : number = 0.0
y? : number = 0.0
}
let p = new Point ( )
delete p. y
ArkTS
// 可以聲明一個(gè)可空類型并使用null作為缺省值
class Point {
x: number | null = 0
y: number | null = 0
}
let p = new Point ( )
p. y = null
相關(guān)約束
對象的屬性名必須是合法的標(biāo)識符 不支持Symbol() API 不支持通過索引訪問字段 僅允許在表達(dá)式中使用typeof運(yùn)算符 不支持in運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性
僅允許在表達(dá)式中使用typeof
運(yùn)算符
規(guī)則: arkts-no-type-query
級別:錯(cuò)誤
ArkTS僅支持在表達(dá)式中使用typeof
運(yùn)算符,。不允許使用typeof
作為類型。
TypeScript
let n1 = 42
let s1 = "foo"
console . log ( typeof n1) // "number"
console . log ( typeof s1) // "string"
let n2: typeof n1
let s2: typeof s1
ArkTS
let n1 = 42
let s1 = "foo"
console . log ( typeof n1) // "number"
console . log ( typeof s1) // "string"
let n2: number
let s2: string
相關(guān)約束
對象的屬性名必須是合法的標(biāo)識符 不支持Symbol() API 不支持通過索引訪問字段 不支持delete運(yùn)算符 不支持in運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性 限制使用標(biāo)準(zhǔn)庫
部分支持instanceof
運(yùn)算符
規(guī)則: arkts-instanceof-ref-types
級別:錯(cuò)誤
在TypeScript中,instanceof
運(yùn)算符的左操作數(shù)的類型必須為any
類型,、對象類型,或者它是類型參數(shù),否則結(jié)果為false
,。在ArkTS中,instanceof
運(yùn)算符的左操作數(shù)的類型必須為引用類型,否則會發(fā)生編譯時(shí)錯(cuò)誤。此外,在ArkTS中,instanceof
運(yùn)算符的左操作數(shù)不能是類型,。
TypeScript
class X {
// ...
}
let a = ( new X ( ) ) instanceof Object // true
let b = ( new X ( ) ) instanceof X // true
let c = X instanceof Object // true, 左操作數(shù)是一個(gè)類型
let d = X instanceof X // false, 左操作數(shù)是一個(gè)類型
ArkTS
class X {
// ...
}
let a = ( new X ( ) ) instanceof Object // true
let b = ( new X ( ) ) instanceof X // true
let c = X instanceof Object // 編譯時(shí)錯(cuò)誤, 左操作數(shù)是一個(gè)類型
let d = X instanceof X // 編譯時(shí)錯(cuò)誤, 左操作數(shù)是一個(gè)類型
不支持in
運(yùn)算符
規(guī)則: arkts-no-in
級別:錯(cuò)誤
由于在ArkTS中,對象布局在編譯時(shí)是已知的并且在運(yùn)行時(shí)無法修改,因此,不支持in
運(yùn)算符,。如果仍需檢查某些類成員是否存在,使用instanceof
代替。
TypeScript
class Person {
name: string = ""
}
let p = new Person ( )
let b = "name" in p // true
ArkTS
class Person {
name: string = ""
}
let p = new Person ( )
let b = p instanceof Person // true,且屬性name一定存在
相關(guān)約束
對象的屬性名必須是合法的標(biāo)識符 不支持Symbol() API 不支持通過索引訪問字段 不支持delete運(yùn)算符 僅允許在表達(dá)式中使用typeof運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性 限制使用標(biāo)準(zhǔn)庫
不支持解構(gòu)賦值
規(guī)則: arkts-no-destruct-assignment
級別:錯(cuò)誤
ArkTS不支持解構(gòu)賦值,??墒褂闷渌娲椒?#xff0c;例如,使用臨時(shí)變量。
TypeScript
let [ one, two] = [ 1 , 2 ] ; // 此處需要分號
[ one, two] = [ two, one]
let head, tail
[ head, ... tail] = [ 1 , 2 , 3 , 4 ]
ArkTS
let arr: number [ ] = [ 1 , 2 ]
let one = arr[ 0 ]
let two = arr[ 1 ]
let tmp = one
one = two
two = tmp
let data: Number[ ] = [ 1 , 2 , 3 , 4 ]
let head = data[ 0 ]
let tail: Number[ ] = [ ]
for ( let i = 1 ; i < data. length; ++ i) {
tail. push ( data[ i] )
}
逗號運(yùn)算符,
僅用在for
循環(huán)語句中
規(guī)則: arkts-no-comma-outside-loops
級別:錯(cuò)誤
為了方便理解執(zhí)行順序,在ArkTS中,逗號運(yùn)算符,
僅適用于for
循環(huán)語句中,。
TypeScript
for ( let i = 0 , j = 0 ; i < 10 ; ++ i, j += 2 ) {
console . log ( i)
console . log ( j)
}
let x = 0
x = ( ++ x, x++ ) // 1
ArkTS
for ( let i = 0 , j = 0 ; i < 10 ; ++ i, j += 2 ) {
console . log ( i)
console . log ( j)
}
// 通過語句表示執(zhí)行順序,而非逗號運(yùn)算符
let x = 0
++ x
x = x++
不支持解構(gòu)變量聲明
規(guī)則: arkts-no-destruct-decls
級別:錯(cuò)誤
ArkTS不支持解構(gòu)變量聲明,。它是一個(gè)依賴于結(jié)構(gòu)兼容性的動(dòng)態(tài)特性并且解構(gòu)聲明中的名稱必須和被解構(gòu)對象中的屬性名稱一致。
TypeScript
class Point {
x: number = 0.0
y: number = 0.0
}
function returnZeroPoint ( ) : Point {
return new Point ( )
}
let { x, y} = returnZeroPoint ( )
ArkTS
class Point {
x: number = 0.0
y: number = 0.0
}
function returnZeroPoint ( ) : Point {
return new Point ( )
}
// 創(chuàng)建一個(gè)局部變量來處理每個(gè)字段:
let zp = returnZeroPoint ( )
let x = zp. x
let y = zp. y
不支持在catch語句標(biāo)注類型
規(guī)則: arkts-no-types-in-catch
級別:錯(cuò)誤
在TypeScript的catch語句中,只能標(biāo)注any
或unknown
類型,。由于ArkTS不支持這些類型,應(yīng)省略類型標(biāo)注,。
TypeScript
try {
// 一些代碼
}
catch ( a: unknown ) {
// 處理異常
}
ArkTS
try {
// 一些代碼
}
catch ( a) {
// 處理異常
}
相關(guān)約束
不支持for .. in
規(guī)則: arkts-no-for-in
級別:錯(cuò)誤
由于在ArkTS中,對象布局在編譯時(shí)是確定的、并且不能在運(yùn)行時(shí)被改變,所以不支持使用for .. in
迭代一個(gè)對象的屬性,。對于數(shù)組來說,可以使用常規(guī)的for
循環(huán),。
TypeScript
let a: number [ ] = [ 1.0 , 2.0 , 3.0 ]
for ( let i in a) {
console . log ( a[ i] )
}
ArkTS
let a: number [ ] = [ 1.0 , 2.0 , 3.0 ]
for ( let i = 0 ; i < a. length; ++ i) {
console . log ( a[ i] )
}
相關(guān)約束
for-of
僅適用于數(shù)組和字符串
規(guī)則: arkts-for-of-str-arr
級別:錯(cuò)誤
ArkTS支持通過for .. of
迭代數(shù)組、字符串和TypedArray
(例如Int32Array
),但不支持迭代對象,。
TypeScript
let a: Set< number > = new Set ( [ 1 , 2 , 3 ] )
for ( let s of a) {
console . log ( s)
}
ArkTS
let a: Set< number > = new Set ( [ 1 , 2 , 3 ] )
let numbers = Array . from ( a. values ( ) )
for ( let n of numbers) {
console . log ( n)
}
相關(guān)約束
不支持映射類型
規(guī)則: arkts-no-mapped-types
級別:錯(cuò)誤
ArkTS不支持映射類型,。使用其他語法來表示相同的語義。
TypeScript
type OptionsFlags< Type> = {
[ Property in keyof Type] : boolean
}
ArkTS
class C {
n: number = 0
s: string = ""
}
class CFlags {
n: boolean = false
s: boolean = false
}
相關(guān)約束
不支持with
語句
規(guī)則: arkts-no-with
級別:錯(cuò)誤
ArkTS不支持with
語句,。使用其他語法來表示相同的語義,。
TypeScript
with ( Math) { // 編譯時(shí)錯(cuò)誤, 但是仍能生成JavaScript代碼
let r: number = 42
console . log ( "Area: " , PI * r * r)
}
ArkTS
let r: number = 42
console . log ( "Area: " , Math. PI * r * r)
限制throw
語句中表達(dá)式的類型
規(guī)則: arkts-limited-throw
級別:錯(cuò)誤
ArkTS只支持拋出Error
類或其派生類的實(shí)例。禁止拋出其他類型(例如number
或string
)的數(shù)據(jù),。
TypeScript
throw 4
throw ""
throw new Error ( )
ArkTS
throw new Error ( )
限制省略函數(shù)返回類型標(biāo)注
規(guī)則: arkts-no-implicit-return-types
級別:錯(cuò)誤
ArkTS在部分場景中支持對函數(shù)返回類型進(jìn)行推斷,。當(dāng)return
語句中的表達(dá)式是對某個(gè)函數(shù)或方法進(jìn)行調(diào)用,且該函數(shù)或方法的返回類型沒有被顯著標(biāo)注時(shí),會出現(xiàn)編譯時(shí)錯(cuò)誤。在這種情況下,請標(biāo)注函數(shù)返回類型,。
TypeScript
// 只有在開啟noImplicitAny選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
function f ( x: number ) {
if ( x <= 0 ) {
return x
}
return g ( x)
}
// 只有在開啟noImplicitAny選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
function g ( x: number ) {
return f ( x - 1 )
}
function doOperation ( x: number , y: number ) {
return x + y
}
console . log ( f ( 10 ) )
console . log ( doOperation ( 2 , 3 ) )
ArkTS
// 需標(biāo)注返回類型:
function f ( x: number ) : number {
if ( x <= 0 ) {
return x
}
return g ( x)
}
// 可以省略返回類型,返回類型可以從f的類型標(biāo)注推導(dǎo)得到
function g ( x: number ) : number {
return f ( x - 1 )
}
// 可以省略返回類型
function doOperation ( x: number , y: number ) {
return x + y
}
console . log ( f ( 10 ) )
console . log ( doOperation ( 2 , 3 ) )
不支持參數(shù)解構(gòu)的函數(shù)聲明
規(guī)則: arkts-no-destruct-params
級別:錯(cuò)誤
ArkTS要求實(shí)參必須直接傳遞給函數(shù),且必須指定到形參,。
TypeScript
function drawText ( { text = "" , location: [ x, y] = [ 0 , 0 ] , bold = false } ) {
console . log ( text)
console . log ( x)
console . log ( y)
console . log ( bold)
}
drawText ( { text: "Hello, world!" , location: [ 100 , 50 ] , bold: true } )
ArkTS
function drawText ( text: String, location: number [ ] , bold: boolean ) {
let x = location[ 0 ]
let y = location[ 1 ]
console . log ( text)
console . log ( x)
console . log ( y)
console . log ( bold)
}
function main ( ) {
drawText ( "Hello, world!" , [ 100 , 50 ] , true )
}
不支持在函數(shù)內(nèi)聲明函數(shù)
規(guī)則: arkts-no-nested-funcs
級別:錯(cuò)誤
ArkTS不支持在函數(shù)內(nèi)聲明函數(shù),。改用lambda函數(shù)。
TypeScript
function addNum ( a: number , b: number ) : void {
// 函數(shù)內(nèi)聲明函數(shù):
function logToConsole ( message: String) : void {
console . log ( message)
}
let result = a + b
// 調(diào)用函數(shù):
logToConsole ( "result is " + result)
}
ArkTS
function addNum ( a: number , b: number ) : void {
// 使用lambda函數(shù)代替聲明函數(shù):
let logToConsole : ( message: string ) => void = ( message: string ) : void => {
console . log ( message)
}
let result = a + b
logToConsole ( "result is " + result)
}
不支持在函數(shù)和類的靜態(tài)方法中使用this
規(guī)則: arkts-no-standalone-this
級別:錯(cuò)誤
ArkTS不支持在函數(shù)和類的靜態(tài)方法中使用this
,。只能在類的實(shí)例方法中使用this
,。
TypeScript
function foo ( i: number ) {
this . count = i // 只有在開啟noImplicitThis選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
}
class A {
count: number = 1
m = foo
}
let a = new A ( )
console . log ( a. count) // 打印“1”
a. m ( 2 )
console . log ( a. count) // 打印“2”
ArkTS
class A {
count: number = 1
m ( i: number ) : void {
this . count = i
}
}
function main ( ) : void {
let a = new A ( )
console . log ( a. count) // 打印"1"
a. m ( 2 )
console . log ( a. count) // 打印"2"
}
相關(guān)約束
不支持Function.apply、Function.bind以及Function.call
不支持生成器函數(shù)
規(guī)則: arkts-no-generators
級別:錯(cuò)誤
目前ArkTS不支持生成器函數(shù),。使用async
或await
機(jī)制進(jìn)行并行任務(wù)處理,。
TypeScript
function * counter ( start: number , end: number ) {
for ( let i = start; i <= end; i++ ) {
yield i
}
}
for ( let num of counter ( 1 , 5 ) ) {
console . log ( num)
}
ArkTS
async function complexNumberProcessing ( n : number ) : Promise < number > {
//一些代碼邏輯
return n
}
async function foo ( ) {
for ( let i = 1 ; i <= 5 ; i++ ) {
console . log ( await complexNumberProcessing ( i) )
}
}
foo ( )
使用instanceof
和as
進(jìn)行類型保護(hù)
規(guī)則: arkts-no-is
級別:錯(cuò)誤
ArkTS不支持is
運(yùn)算符,必須用instanceof
運(yùn)算符替代。在使用之前,必須使用as
運(yùn)算符將對象轉(zhuǎn)換為需要的類型,。
TypeScript
class Foo {
foo: number = 0
common: string = ""
}
class Bar {
bar: number = 0
common: string = ""
}
function isFoo ( arg: any ) : arg is Foo {
return arg. foo !== undefined
}
function doStuff ( arg: Foo | Bar) {
if ( isFoo ( arg) ) {
console . log ( arg. foo) // OK
console . log ( arg. bar) // 編譯時(shí)錯(cuò)誤
} else {
console . log ( arg. foo) // 編譯時(shí)錯(cuò)誤
console . log ( arg. bar) // OK
}
}
doStuff ( { foo: 123 , common: '123' } )
doStuff ( { bar: 123 , common: '123' } )
ArkTS
class Foo {
foo: number = 0
common: string = ""
}
class Bar {
bar: number = 0
common: string = ""
}
function isFoo ( arg: Object) : boolean {
return arg instanceof Foo
}
function doStuff ( arg: Object) : void {
if ( isFoo ( arg) ) {
let fooArg = arg as Foo
console . log ( fooArg. foo) // OK
console . log ( arg. bar) // 編譯時(shí)錯(cuò)誤
} else {
let barArg = arg as Bar
console . log ( arg. foo) // 編譯時(shí)錯(cuò)誤
console . log ( barArg. bar) // OK
}
}
function main ( ) : void {
doStuff ( new Foo ( ) )
doStuff ( new Bar ( ) )
}
不支持keyof
運(yùn)算符
規(guī)則: arkts-no-keyof
級別:錯(cuò)誤
在ArkTS中,由于對象布局在編譯時(shí)就確定了,且不能在運(yùn)行時(shí)被更改,因此,不支持使用keyof
運(yùn)算符,。直接訪問對象的屬性。
TypeScript
class Point {
x: number = 1
y: number = 2
}
type PointKeys = keyof Point // PointKeys表示Point屬性名稱組成的聯(lián)合類型
function getPropertyValue ( obj: Point, key: PointKeys) {
return obj[ key]
}
let obj = new Point ( )
console . log ( getPropertyValue ( obj, "x" ) ) // 打印"1"
console . log ( getPropertyValue ( obj, "y" ) ) // 打印"2"
ArkTS
class Point {
x: number = 1
y: number = 2
}
function getPropertyValue ( obj: Point, key: string ) : number {
if ( key == "x" ) {
return obj. x
}
if ( key == "y" ) {
return obj. y
}
throw new Error ( ) // 處理沒有該屬性的分支
return 0
}
function main ( ) : void {
let obj = new Point ( )
console . log ( getPropertyValue ( obj, "x" ) ) // 打印"1"
console . log ( getPropertyValue ( obj, "y" ) ) // 打印"2"
}
展開運(yùn)算符僅支持函數(shù)剩余參數(shù)為數(shù)組類型
規(guī)則: arkts-no-spread
級別:錯(cuò)誤
展開運(yùn)算符唯一支持的場景是函數(shù)剩余參數(shù)為數(shù)組類型,包括TypedArray
(例如Int32Array
),。
TypeScript
function foo ( x : number , y : number , z : number ) {
console . log ( x, y, z)
}
let args : [ number , number , number ] = [ 0 , 1 , 2 ]
foo ( ... args)
let list1 = [ 1 , 2 ]
let list2 = [ ... list1, 3 , 4 ]
let point2d = { x: 1 , y: 2 }
let point3d = { ... point2d, z: 3 }
ArkTS
function sum_numbers ( ... numbers: number [ ] ) : number {
let res = 0
for ( let n of numbers)
res += n
return res
}
console . log ( sum_numbers ( 1 , 2 , 3 ) )
function log_numbers ( x : number , y : number , z : number ) {
console . log ( x, y, z)
}
let numbers: number [ ] = [ 1 , 2 , 3 ]
log_numbers ( numbers[ 0 ] , numbers[ 1 ] , numbers[ 2 ] )
let list1 : number [ ] = [ 1 , 2 ]
let list2 : number [ ] = [ list1[ 0 ] , list1[ 1 ] , 3 , 4 ]
class Point2D {
x: number = 0 ; y: number = 0
}
class Point3D {
x: number = 0 ; y: number = 0 ; z: number = 0
constructor ( p2d: Point2D, z: number ) {
this . x = p2d. x
this . y = p2d. y
this . z = z
}
}
let p3d = new Point3D ( { x: 1 , y: 2 } as Point2D, 3 )
console . log ( p3d. x, p3d. y, p3d. z)
接口不能繼承具有相同屬性的兩個(gè)接口
規(guī)則: arkts-no-extend-same-prop
級別:錯(cuò)誤
在TypeScript中,如果一個(gè)接口繼承了具有相同方法的兩個(gè)接口,則該接口必須使用聯(lián)合類型來聲明該方法,。在ArkTS中,由于一個(gè)接口中不能包含兩個(gè)無法區(qū)分的方法(例如兩個(gè)參數(shù)列表相同但返回類型不同的方法),因此,接口不能繼承具有相同屬性的兩個(gè)接口。
TypeScript
interface Mover {
getStatus ( ) : { speed: number }
}
interface Shaker {
getStatus ( ) : { frequency: number }
}
interface MoverShaker extends Mover , Shaker {
getStatus ( ) : {
speed: number
frequency: number
}
}
class C implements MoverShaker {
private speed: number = 0
private frequency: number = 0
getStatus ( ) {
return { speed: this . speed, frequency: this . frequency }
}
}
ArkTS
class MoveStatus {
public speed : number
constructor ( ) {
this . speed = 0
}
}
interface Mover {
getMoveStatus ( ) : MoveStatus
}
class ShakeStatus {
public frequency : number
constructor ( ) {
this . frequency = 0
}
}
interface Shaker {
getShakeStatus ( ) : ShakeStatus
}
class MoveAndShakeStatus {
public speed : number
public frequency : number
constructor ( ) {
this . speed = 0
this . frequency = 0
}
}
class C implements Mover , Shaker {
private move_status : MoveStatus
private shake_status : ShakeStatus
constructor ( ) {
this . move_status = new MoveStatus ( )
this . shake_status = new ShakeStatus ( )
}
public getMoveStatus ( ) : MoveStatus {
return this . move_status
}
public getShakeStatus ( ) : ShakeStatus {
return this . shake_status
}
public getStatus ( ) : MoveAndShakeStatus {
return {
speed: this . move_status. speed,
frequency: this . shake_status. frequency
}
}
}
不支持聲明合并
規(guī)則: arkts-no-decl-merging
級別:錯(cuò)誤
ArkTS不支持類,、接口的聲明合并,。
TypeScript
interface Document {
createElement ( tagName: any ) : Element
}
interface Document {
createElement ( tagName: string ) : HTMLElement
}
interface Document {
createElement ( tagName: number ) : HTMLDivElement
createElement ( tagName: boolean ) : HTMLSpanElement
createElement ( tagName: string , value: number ) : HTMLCanvasElement
}
ArkTS
interface Document {
createElement ( tagName: number ) : HTMLDivElement
createElement ( tagName: boolean ) : HTMLSpanElement
createElement ( tagName: string , value: number ) : HTMLCanvasElement
createElement ( tagName: string ) : HTMLElement
createElement ( tagName: Object) : Element
}
接口不能繼承類
規(guī)則: arkts-extends-only-class
級別:錯(cuò)誤
ArkTS不支持接口繼承類。接口只能繼承接口,。
TypeScript
class Control {
state: number = 0
}
interface SelectableControl extends Control {
select ( ) : void
}
ArkTS
interface Control {
state: number
}
interface SelectableControl extends Control {
select ( ) : void
}
禁止運(yùn)行時(shí)檢查對象屬性
規(guī)則: arkts-no-prop-existence-check
級別:錯(cuò)誤
ArkTS中,對象布局在編譯時(shí)就確定了,且不能在運(yùn)行時(shí)被更改,。禁止運(yùn)行時(shí)檢查對象屬性。使用as
運(yùn)算符進(jìn)行類型轉(zhuǎn)換以訪問相應(yīng)的屬性和方法,。訪問對象中不存在的屬性將導(dǎo)致編譯時(shí)錯(cuò)誤,。
TypeScript
class A {
foo ( ) { }
bar ( ) { }
}
function getSomeObject ( ) {
return new A ( )
}
let obj: any = getSomeObject ( )
if ( obj && obj. foo && obj. bar) {
console . log ( "Yes" ) // 此示例中將打印 "Yes"
} else {
console . log ( "No" )
}
ArkTS
class A {
foo ( ) : void { }
bar ( ) : void { }
}
function getSomeObject ( ) : A {
return new A ( )
}
function main ( ) : void {
let tmp: Object = getSomeObject ( )
let obj: A = tmp as A
obj. foo ( ) // OK
obj. bar ( ) // OK
obj. some_foo ( ) // 編譯時(shí)錯(cuò)誤:方法some_foo不存在于此類型上
}
相關(guān)約束
對象的屬性名必須是合法的標(biāo)識符 不支持Symbol() API 不支持通過索引訪問字段 不支持delete運(yùn)算符 僅允許運(yùn)算符typeof在表達(dá)式上下文中使用 不支持in運(yùn)算符 限制使用標(biāo)準(zhǔn)庫
不支持構(gòu)造函數(shù)類型
規(guī)則: arkts-no-ctor-signatures-funcs
級別:錯(cuò)誤
ArkTS不支持使用構(gòu)造函數(shù)類型。改用lambda函數(shù),。
TypeScript
class Person {
constructor (
name: string ,
age: number
) { }
}
type PersonCtor = new ( name: string , age: number ) => Person
function createPerson ( Ctor: PersonCtor, name: string , age: number ) : Person
{
return new Ctor ( name, age)
}
const person = createPerson ( Person, 'John' , 30 )
ArkTS
class Person {
constructor (
name: string ,
age: number
) { }
}
type PersonCtor = ( n: string , a: number ) => Person
function createPerson ( Ctor: PersonCtor, n: string , a: number ) : Person {
return Ctor ( n, a)
}
let Impersonizer: PersonCtor = ( n: string , a: number ) : Person => {
return new Person ( n, a)
}
const person = createPerson ( Impersonizer, "John" , 30 )
只能使用類型相同的編譯時(shí)表達(dá)式初始化枚舉成員
規(guī)則: arkts-no-enum-mixed-types
級別:錯(cuò)誤
ArkTS不支持使用在運(yùn)行期間才能計(jì)算的表達(dá)式來初始化枚舉成員,。此外,枚舉中所有顯式初始化的成員必須具有相同的類型。
TypeScript
enum E1 {
A = 0xa ,
B = 0xb ,
C = Math. random ( ) ,
D = 0xd ,
E // 推斷出0xe
}
enum E2 {
A = 0xa ,
B = "0xb" ,
C = 0xc ,
D = "0xd"
}
ArkTS
enum E1 {
A = 0xa ,
B = 0xb ,
C = 0xc ,
D = 0xd ,
E // 推斷出0xe
}
enum E2 {
A = "0xa" ,
B = "0xb" ,
C = "0xc" ,
D = "0xd"
}
不支持enum
聲明合并
規(guī)則: arkts-no-enum-merging
級別:錯(cuò)誤
ArkTS不支持enum
聲明合并,。
TypeScript
enum Color {
RED ,
GREEN
}
enum Color {
YELLOW = 2
}
enum Color {
BLACK = 3 ,
BLUE
}
ArkTS
enum Color {
RED ,
GREEN ,
YELLOW ,
BLACK ,
BLUE
}
命名空間不能被用作對象
規(guī)則: arkts-no-ns-as-obj
級別:錯(cuò)誤
ArkTS不支持將命名空間用作對象,。可以使用類或模塊,。
TypeScript
namespace MyNamespace {
export let x: number
}
let m = MyNamespace
m. x = 2
ArkTS
namespace MyNamespace {
export let x: number
}
MyNamespace. x = 2
不支持命名空間中的非聲明語句
規(guī)則: arkts-no-ns-statements
級別:錯(cuò)誤
ArkTS不支持命名空間中的非聲明語句,。可以將非聲明語句寫在函數(shù)中,。
TypeScript
namespace A {
export let x: number
x = 1
}
ArkTS
namespace A {
export let x: number
export function init ( ) {
x = 1
}
}
// 調(diào)用初始化函數(shù)來執(zhí)行:
A . init ( )
不支持import type
規(guī)則: arkts-no-special-imports
級別:錯(cuò)誤
ArkTS不支持import type
,。改為import
。
TypeScript
// 通用導(dǎo)入語法
import { APIResponseType } from "api"
// 導(dǎo)入類型
import type { APIResponseType } from "api"
ArkTS
import { APIResponseType } from "api"
相關(guān)約束
不支持僅為副作用而導(dǎo)入一個(gè)模塊 不支持import default as … 不支持require和import賦值表達(dá)式
不支持僅為副作用而導(dǎo)入一個(gè)模塊
規(guī)則: arkts-no-side-effects-imports
級別:錯(cuò)誤
ArkTS不支持window
等全局變量,避免模塊導(dǎo)入時(shí)產(chǎn)生副作用,??梢酝ㄟ^*
語法獲取所有導(dǎo)出的變量。
TypeScript
// === “path/to/module.ts”中的模塊
export const EXAMPLE_VALUE = 42
// 設(shè)置全局變量
window. MY_GLOBAL_VAR = "Hello, world!"
//==== 使用此模塊:
import "path/to/module"
ArkTS
import * as ns from "path/to/module"
不支持import default as ...
規(guī)則: arkts-no-import-default-as
級別:錯(cuò)誤
ArkTS不支持import default as ...
語法,。使用顯式的import ... from ...
語法,。
TypeScript
import { default as d } from "mod"
ArkTS
import d from "mod"
不支持require
和import
賦值表達(dá)式
規(guī)則: arkts-no-require
級別:錯(cuò)誤
ArkTS不支持通過require
導(dǎo)入,也不支持import
賦值表達(dá)式,。改用import
。
TypeScript
import m = require ( "mod" )
ArkTS
import * as m from "mod"
相關(guān)約束
部分支持重導(dǎo)出
規(guī)則: arkts-limited-reexport
級別:錯(cuò)誤
ArkTS支持命名重導(dǎo)出和重命名重導(dǎo)出,。支持export * ...
的語法,不支持export * as ...
的語法,。
TypeScript
// module1
export class Class1 {
// ...
}
export class Class2 {
// ...
}
// module2
export * as utilities from "module1"
// consumer模塊
import { utilities } from "module2"
const myInstance = new MyClass ( )
ArkTS
// module1
export class Class1 {
// ...
}
export class Class2 {
// ...
}
// module2
export { Class1 } from "module1"
export { C2 as Class2 } from "module1"
// 支持以下語法
// export * from "module1"
// consumer模塊
import { Class1, Class2 } from "module2"
const myInstance = new MyClass ( )
相關(guān)約束
不支持export = ...
語法
規(guī)則: arkts-no-export-assignment
級別:錯(cuò)誤
ArkTS不支持export = ...
語法,。改用常規(guī)的export
或import
,。
TypeScript
// module1
export = Point
class Point {
constructor ( x: number , y: number ) { }
static origin = new Point ( 0 , 0 )
}
// module2
import Pt = require ( "module1" )
let p = Pt. origin
ArkTS
// module1
export class Point {
constructor ( x: number , y: number ) { }
static origin = new Point ( 0 , 0 )
}
// module2
import * as Pt from "module1"
let p = Pt. origin
相關(guān)約束
不支持require和import賦值表達(dá)式 部分支持重導(dǎo)出
不支持export type
規(guī)則: arkts-no-special-exports
級別:錯(cuò)誤
ArkTS不支持export type
。改用export
,。
TypeScript
// 顯式導(dǎo)出class:
export class Class1 {
// ...
}
// 聲明一個(gè)類,之后通過`export type`導(dǎo)出
class Class2 {
// ...
}
// 不支持
export type { Class2 }
ArkTS
// 顯式導(dǎo)出class:
export class Class1 {
// ...
}
// 顯式導(dǎo)出class:
export class Class2 {
// ...
}
不支持ambient module聲明
規(guī)則: arkts-no-ambient-decls
級別:錯(cuò)誤
ArkTS不支持ambient module聲明,因?yàn)锳rkTS本身有與JavaScript交互的機(jī)制,。
TypeScript
declare module "someModule" {
export function normalize ( s : string ) : string ;
}
ArkTS
// 從原始模塊中導(dǎo)入需要的內(nèi)容
import { normalize } from "someModule"
相關(guān)約束
不支持在模塊名中使用通配符 模塊標(biāo)識符中不允許使用.js擴(kuò)展名
不支持在模塊名中使用通配符
規(guī)則: arkts-no-module-wildcards
級別:錯(cuò)誤
由于在ArkTS中,導(dǎo)入是編譯時(shí)而非運(yùn)行時(shí)行為,因此,不支持在模塊名中使用通配符。
TypeScript
// 聲明
declare module "*!text" {
const content: string
export default content
}
import fileContent from "some.txt!text"
ArkTS
// 聲明
declare namespace N {
function foo ( x: number ) : number
}
import * as m from "module"
console . log ( "N.foo called: " , N . foo ( 42 ) )
相關(guān)約束
不支持ambient module聲明 不支持通用模塊定義(UMD) 模塊標(biāo)識符中不允許使用.js擴(kuò)展名
不支持通用模塊定義(UMD)
規(guī)則: arkts-no-umd
級別:錯(cuò)誤
ArkTS不支持通用模塊定義(UMD),。因?yàn)樵贏rkTS中沒有“腳本”的概念(相對于“模塊”),。此外,在ArkTS中,導(dǎo)入是編譯時(shí)而非運(yùn)行時(shí)特性。改用export
和import
語法,。
TypeScript
// math-lib.d.ts
export const isPrime ( x: number ) : boolean
export as namespace mathLib
// 腳本中
mathLib. isPrime ( 2 )
ArkTS
// math-lib.d.ts
namespace mathLib {
export isPrime ( x: number ) : boolean
}
// 程序中
import { mathLib } from "math-lib"
mathLib. isPrime ( 2 )
相關(guān)約束
模塊標(biāo)識符中不允許使用.js擴(kuò)展名
規(guī)則: arkts-no-js-extension
級別:錯(cuò)誤
ArkTS不允許在模塊標(biāo)識符中使用.js
擴(kuò)展名,因?yàn)锳rkTS本身有與JavaScript交互的機(jī)制,。
TypeScript
import { something } from "module.js"
ArkTS
import { something } from "module"
相關(guān)約束
不支持ambient module聲明 不支持在模塊名中使用通配符
不支持new.target
規(guī)則: arkts-no-new-target
級別:錯(cuò)誤
ArkTS沒有原型的概念,因此不支持new.target
。此特性不符合靜態(tài)類型的原則,。
TypeScript
class CustomError extends Error {
constructor ( message? : string ) {
// 'Error'在此處斷開原型鏈
super ( message)
// 恢復(fù)原型鏈
Object. setPrototypeOf ( this , new . target. prototype)
}
}
ArkTS
class CustomError extends Error {
constructor ( message? : string ) {
// 調(diào)用父類構(gòu)造函數(shù),繼承鏈?zhǔn)庆o態(tài)的,且不能在運(yùn)行時(shí)被改變
super ( message)
console . log ( this instanceof Error ) // true
}
}
let ce = new CustomError ( )
相關(guān)約束
不支持確定賦值斷言
規(guī)則: arkts-no-definite-assignment
級別:錯(cuò)誤
ArkTS不支持確定賦值斷言let v!: T
,這是一種過度的編譯器提示,。改用帶初始化的聲明。
TypeScript
let x! : number // 提示:在使用前將x初始化
initialize ( )
function initialize ( ) {
x = 10
}
console . log ( "x = " + x)
ArkTS
function initialize ( ) : number {
return 10
}
let x: number = initialize ( )
console . log ( "x = " + x)
不支持IIFE(立即調(diào)用函數(shù)表達(dá)式)作為命名空間的聲明
規(guī)則: arkts-no-iife
級別:錯(cuò)誤
由于在ArkTS中,匿名函數(shù)不能作為命名空間,因此不支持IIFE作為命名空間的聲明,。請使用命名空間的常規(guī)語法,。
TypeScript
const C = ( function ( ) {
class Cl {
static static_value = "static_value" ;
static any_value: any = "any_value" ;
string_field = "string_field" ;
}
return Cl;
} ) ( ) ;
C . prop = 2 ;
ArkTS
namespace C {
// ...
}
不支持在原型上賦值
規(guī)則: arkts-no-prototype-assignment
級別:錯(cuò)誤
ArkTS沒有原型的概念,因此不支持在原型上賦值。此特性不符合靜態(tài)類型的原則,。
TypeScript
var C = function ( p) {
this . p = p // 只有在開啟noImplicitThis選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
}
C . prototype = {
m ( ) {
console . log ( this . p)
}
}
C . prototype. q = function ( r: number ) {
return this . p == r
}
ArkTS
class C {
p: number = 0
m ( ) {
console . log ( this . p)
}
q ( r: number ) {
return this . p == r
}
}
相關(guān)約束
不支持globalThis
規(guī)則: arkts-no-globalthis
級別:錯(cuò)誤
由于ArkTS不支持動(dòng)態(tài)更改對象的布局,因此不支持全局作用域和globalThis
,。
TypeScript
// 全局文件中
var abc = 100
// 從上面引用'abc'
globalThis. abc = 200
ArkTS
// file1
export let abc : number = 0
// file2
import * as M from "file1"
M . abc = 200
相關(guān)約束
不支持聲明函數(shù)的屬性 標(biāo)準(zhǔn)庫使用限制
不支持一些utility類型
規(guī)則: arkts-no-utility-types
級別:錯(cuò)誤
ArkTS僅支持Partial
和Record
,不支持TypeScript中其他的Utility Types
。
對于Record<K, V>類型,表達(dá)式 rec[index]的類型是 V | undefined ,。 對于Record
類型,鍵-值中的值的類型必須是可選類型或者包含undefined
的聯(lián)合類型,。
TypeScript
type Person = {
name: string
age: number
location: string
}
type QuantumPerson = Omit< Person, "location" >
let persons : Record< string , Person> = {
"Alice" : {
name: "Alice" ,
age: 32 ,
location: "Shanghai"
} ,
"Bob" : {
name: "Bob" ,
age: 48 ,
location: "New York"
}
}
console . log ( persons[ "Bob" ] . age)
console . log ( persons[ "Rob" ] . age) // 運(yùn)行時(shí)異常
ArkTS
class Person {
name: string = ""
age: number = 0
location: string = ""
}
class QuantumPerson {
name: string = ""
age: number = 0
}
type OptionalPerson = Person | undefined
let persons : Record< string , OptionalPerson> = {
// 或者
// let persons : Record<string, Person | undefined> = {
"Alice" : {
name: "Alice" ,
age: 32 ,
location: "Shanghai"
} ,
"Bob" : {
name: "Bob" ,
age: 48 ,
location: "New York"
}
}
console . log ( persons[ "Bob" ] ! . age)
if ( persons[ "Rob" ] ) { // 值檢查,不會運(yùn)行時(shí)拋異常
console . log ( persons[ "Rob" ] . age)
}
不支持對函數(shù)聲明屬性
規(guī)則: arkts-no-func-props
級別:錯(cuò)誤
由于ArkTS不支持動(dòng)態(tài)改變函數(shù)對象布局,因此,不支持對函數(shù)聲明屬性。
TypeScript
class MyImage {
// ...
}
function readImage (
path: string , callback : ( err: any , image: MyImage) => void
)
{
// ...
}
function readFileSync ( path : string ) : number [ ] {
return [ ]
}
function decodeImageSync ( contrents : number [ ] ) {
// ...
}
readImage. sync = ( path: string ) => {
const contents = readFileSync ( path)
return decodeImageSync ( contents)
}
ArkTS
class MyImage {
// ...
}
async function readImage (
path: string , callback : ( err: Error, image: MyImage) => void
) : Promise < MyImage>
{
return await new MyImage ( )
}
function readImageSync ( path: string ) : MyImage {
return new MyImage ( )
}
相關(guān)約束
不支持Function.apply
,、Function.bind
以及Function.call
規(guī)則: arkts-no-func-apply-bind-call
級別:錯(cuò)誤
ArkTS不允許使用標(biāo)準(zhǔn)庫函數(shù)Function.apply
,、Function.bind
以及Function.call
。標(biāo)準(zhǔn)庫使用這些函數(shù)來顯式設(shè)置被調(diào)用函數(shù)的this
參數(shù),。在ArkTS中,this
的語義僅限于傳統(tǒng)的OOP風(fēng)格,函數(shù)體中禁止使用this
,。
TypeScript
class P1 {
firstName: string = "Mary" ;
}
class P2 {
firstName: string = "Jack" ;
fullName ( ) : string {
return this . firstName
}
}
const person2 = new P2 ( ) ;
const person1 = new P1 ( ) ;
// 將會打印 Mary
console . log ( person2. fullName . apply ( person1) )
ArkTS
class Person {
firstName : string
constructor ( firstName : string ) {
this . firstName = firstName
}
fullName ( ) : string {
return this . firstName
}
}
let person = new Person ( "" )
let person1 = new Person ( "Mary" )
// 將打印“Mary”
console . log ( person1. fullName ( ) )
相關(guān)約束
不支持readonly
修飾函數(shù)參數(shù)
規(guī)則: arkts-no-readonly-params
級別:錯(cuò)誤
當(dāng)前ArkTS中,readonly
可以用于修飾屬性,但不能用于修飾函數(shù)參數(shù)。
TypeScript
function foo ( arr: readonly string [ ] ) {
arr. slice ( ) // OK
arr. push ( "hello!" ) // 編譯時(shí)錯(cuò)誤
}
ArkTS
function foo ( arr: string [ ] ) {
arr. slice ( ) // OK
arr. push ( "hello!" ) // OK
}
不支持as const
斷言
規(guī)則: arkts-no-as-const
級別:錯(cuò)誤
ArkTS不支持as const
斷言,。在標(biāo)準(zhǔn)TypeScript中,as const
用于標(biāo)注字面量的相應(yīng)字面量類型,而ArkTS不支持字面量類型,。
TypeScript
// 'hello'類型
let x = "hello" as const
// 'readonly [10, 20]'類型
let y = [ 10 , 20 ] as const
// '{ readonly text: "hello" }'類型
let z = { text: "hello" } as const
ArkTS
// 'string'類型
let x : string = "hello"
// 'number[]'類型
let y : number [ ] = [ 10 , 20 ]
class Label {
text : string = ""
}
// 'Label'類型
let z : Label = {
text: "hello"
}
不支持導(dǎo)入斷言
規(guī)則: arkts-no-import-assertions
級別:錯(cuò)誤
由于在ArkTS中,導(dǎo)入是編譯時(shí)而非運(yùn)行時(shí)特性,因此,ArkTS不支持導(dǎo)入斷言。在運(yùn)行時(shí)檢查導(dǎo)入的API是否正確,對于靜態(tài)類型的語言來說是沒有意義的,。改用常規(guī)的import
語法,。
TypeScript
import { obj } from "something.json" assert { type: "json" }
ArkTS
// 編譯時(shí)將檢查導(dǎo)入T的正確性
import { something } from "module"
相關(guān)約束
不支持在模塊名中使用通配符 不支持通用模塊定義(UMD) 不支持運(yùn)行時(shí)導(dǎo)入斷言
限制使用標(biāo)準(zhǔn)庫
規(guī)則: arkts-limited-stdlib
級別:錯(cuò)誤
ArkTS不允許使用TypeScript或JavaScript標(biāo)準(zhǔn)庫中的某些接口,。大部分接口與動(dòng)態(tài)特性有關(guān)。ArkTS中禁止使用以下接口:
全局對象的屬性和方法:eval
,、 Infinity
,、NaN
、isFinite
,、isNaN
,、parseFloat
、parseInt
,、 Encode
,、Decode
、ParseHexOctet
Object
:__proto__
,、__defineGetter__
,、__defineSetter__
、 __lookupGetter__
,、__lookupSetter__
,、assign
、create
,、 defineProperties
,、defineProperty
、entries
,、freeze
,、 fromEntries
、getOwnPropertyDescriptor
,、getOwnPropertyDescriptors
,、 getOwnPropertyNames
、getOwnPropertySymbols
,、getPrototypeOf
,、 hasOwn
、hasOwnProperty
,、is
,、isExtensible
、isFrozen
,、 isPrototypeOf
,、isSealed
、keys
,、preventExtensions
,、 propertyIsEnumerable
、seal
,、setPrototypeOf
,、values
Reflect
:apply
,、construct
、defineProperty
,、deleteProperty
,、 get
、getOwnPropertyDescriptor
,、getPrototypeOf
,、has
、 isExtensible
,、ownKeys
,、preventExtensions
,、set
, setPrototypeOf
Proxy
:handler.apply()
,、handler.construct()
、 handler.defineProperty()
,、handler.deleteProperty()
,、handler.get()
、 handler.getOwnPropertyDescriptor()
,、handler.getPrototypeOf()
,、 handler.has()
、handler.isExtensible()
,、handler.ownKeys()
,、 handler.preventExtensions()
、handler.set()
,、handler.setPrototypeOf()
Array
:isArray
ArrayBuffer
:isView
相關(guān)約束
對象的屬性名必須是合法的標(biāo)識符 不支持Symbol() API 不支持通過索引訪問字段 僅允許在表達(dá)式中使用typeof運(yùn)算符 不支持in運(yùn)算符 禁止運(yùn)行時(shí)檢查對象屬性 不支持globalThis
強(qiáng)制開啟嚴(yán)格類型檢查
規(guī)則: arkts-strict-typing
級別:錯(cuò)誤
在ArkTS中,以下TypeScript的嚴(yán)格類型檢查選項(xiàng)必須打開:noImplicitReturns
, strictFunctionTypes
, strictNullChecks
, strictPropertyInitialization
,。
TypeScript
class C {
n: number // 只有在開啟strictPropertyInitialization選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
s: string // 只有在開啟strictPropertyInitialization選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
}
// 只有在開啟noImplicitReturns選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
function foo ( s: string ) : string {
if ( s != "" ) {
console . log ( s)
return s
} else {
console . log ( s)
}
}
let n: number = null // 只有在開啟strictNullChecks選項(xiàng)時(shí)會產(chǎn)生編譯時(shí)錯(cuò)誤
ArkTS
class C {
n: number = 0
s: string = ""
}
function foo ( s: string ) : string {
console . log ( s)
return s
}
let n1: number | null = null
let n2: number = 0
相關(guān)約束
使用具體的類型而非any或unknown 不允許通過注釋關(guān)閉類型檢查
不允許通過注釋關(guān)閉類型檢查
規(guī)則: arkts-strict-typing-required
級別:錯(cuò)誤
在ArkTS中,類型檢查不是可選項(xiàng)。不允許通過注釋關(guān)閉類型檢查,不支持使用@ts-ignore
和@ts-nocheck
,。
TypeScript
// @ts-nocheck
// ...
// 關(guān)閉了類型檢查后的代碼
// ...
let s1: string = null // 沒有報(bào)錯(cuò)
// @ts-ignore
let s2: string = null // 沒有報(bào)錯(cuò)
ArkTS
let s1: string | null = null // 沒有報(bào)錯(cuò),合適的類型
let s2: string = null // 編譯時(shí)報(bào)錯(cuò)
相關(guān)約束
使用具體的類型而非any或unknown 強(qiáng)制開啟嚴(yán)格類型檢查
允許ArkTS代碼導(dǎo)入TS代碼, 不允許TS代碼導(dǎo)入ArkTS代碼
規(guī)則: arkts-no-ts-deps
級別:錯(cuò)誤
ArkTS中的代碼可以導(dǎo)入來自標(biāo)準(zhǔn)TypeScript的代碼,而標(biāo)準(zhǔn)TypeScript的代碼不能導(dǎo)入來自ArkTS中的代碼,。
TypeScript
// app.ets
export class C {
// ...
}
// lib.ts
import { C } from "app"
ArkTS
// lib1.ets
export class C {
// ...
}
// lib2.ets
import { C } from "lib1"
除了ArkUI中的裝飾器,不允許使用其他裝飾器
規(guī)則: arkts-no-decorators-except-arkui
級別:錯(cuò)誤
現(xiàn)在,ArkTS中只支持ArkUI中的裝飾器。使用其他裝飾器會造成編譯時(shí)錯(cuò)誤,。
TypeScript
function classDecorator ( x: number , y: number ) : void {
//
}
@ classDecorator
class BugReport {
}
ArkTS
function classDecorator ( x: number , y: number ) : void {
//
}
@ classDecorator // 編譯時(shí)錯(cuò)誤
class BugReport {
}
class
不能被用作對象
規(guī)則: arkts-no-classes-as-obj
級別:錯(cuò)誤
在ArkTS中,class
聲明的是一個(gè)新的類型,不是一個(gè)值,。因此,不支持將class
用作對象(例如將class
賦值給一個(gè)對象)。
TypeScript
class C {
s: string = ""
n: number = 0
}
let c = C
不支持在import
語句前使用其他語句
規(guī)則: arkts-no-misplaced-imports
級別:錯(cuò)誤
在ArkTS中,除動(dòng)態(tài)import
語句外,所有import
語句需要放在所有其他語句之前,。
TypeScript
class C {
s: string = ""
n: number = 0
}
import foo from "module1"
ArkTS
import foo from "module1"
class C {
s: string = ""
n: number = 0
}
參考:
https:///openharmony/docs/blob/master/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md#%E7%BA%A6%E6%9D%9F%E8%AF%B4%E6%98%8E