99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

ArkTS不支持結(jié)構(gòu)化類型(Structural Typing)詳解

2024-12-04 09:39 更新

大家好,我是 V 哥,今天有粉絲問 V 哥,ArkTS不支持structural typing 是什么意思?ArkTS不支持接口嗎?

輸入圖片說明

輸入圖片說明

V哥把問題整理一下,分享給大家,尤其對TypeScript不熟的小伙伴,看到官網(wǎng)這句表述,是不是也是一頭霧水,不知所措,前端小伙伴就不用說了,出門右轉(zhuǎn)吧,因為對你來說,這是個很簡單的問題。

首先 關(guān)于 structural typing(結(jié)構(gòu)化類型) 是 TypeScript 中的特性,我們先來介紹一下。

TypeScript 中的結(jié)構(gòu)化類型(Structural Typing)特性

TypeScript 是一種靜態(tài)類型的超集于 JavaScript 的編程語言,它引入了類型系統(tǒng)來增強代碼的可維護性和可讀性。TypeScript 的類型系統(tǒng)基于結(jié)構(gòu)化類型(Structural Typing),這意味著類型的兼容性和等價性是基于類型實際的結(jié)構(gòu)或定義來確定的,而不是基于其名稱或聲明位置,這與像 C# 或 C 這樣的語言中的命名類型系統(tǒng)(Nominal Typing)不同。

結(jié)構(gòu)化類型的核心原則

  1. 形狀兼容性(Shape Compatibility):如果兩個類型具有相同的屬性和方法,并且這些成員的類型也匹配,那么這兩個類型就是兼容的,無論它們的名稱是什么。
  2. 允許額外屬性(Extra Properties Are Allowed):一個對象可以擁有在類型定義中沒有的額外屬性,但仍然可以被賦值給該類型。
  3. 參數(shù)雙變(Parameter Bivariance):對于函數(shù)類型,只要函數(shù)簽名中的其他部分匹配,就可以允許參數(shù)類型有額外的特定性或更廣泛的通用性。

看個代碼案例

基本對象兼容性

interface Point2D {
    x: number;
    y: number;
}


interface Point3D {
    x: number;
    y: number;
    z: number;
}


const point2D: Point2D = { x: 1, y: 2 };
const point3D: Point3D = { x: 1, y: 2, z: 3 };


// 將 Point3D 賦值給 Point2D
const anotherPoint2D: Point2D = point3D; // 允許,因為 Point3D 包含了 Point2D 所需的所有屬性
console.log(anotherPoint2D); // 輸出: { x: 1, y: 2, z: 3 }

我們看到在這個例子中,Point3D 包含了 Point2D 所需的所有屬性(xy),并且還有一個額外的 z 屬性。TypeScript 允許這種賦值,因為它是基于結(jié)構(gòu)的。

函數(shù)兼容性

函數(shù)類型的兼容性也遵循結(jié)構(gòu)化類型規(guī)則,函數(shù)的兼容性取決于其參數(shù)和返回類型。只要函數(shù)簽名中的其他部分匹配,就可以允許參數(shù)類型有額外的特定性或更廣泛的通用性。

type Sum = (a: number, b: number) => number;
const sum: Sum = (a, b) => a + b;


const extendedSum = (a: number, b: number, c: number) => a + b + c;


// 將 extendedSum 賦值給 newSum
const newSum: Sum = (a: number, b: number) => extendedSum(a, b, 0);
console.log(newSum(1, 2)); // 輸出: 3

我們看到在這個例子中,extendedSum 函數(shù)接受三個參數(shù),但我們只使用了前兩個參數(shù)來創(chuàng)建一個新的 Sum 類型的函數(shù) newSum。TypeScript 允許這種賦值,因為 newSum 的結(jié)構(gòu)與 Sum 兼容。

結(jié)構(gòu)化類型的優(yōu)勢

  1. 靈活性:能夠靈活地分配具有相同結(jié)構(gòu)的不同類型。
  2. 與 JavaScript 的兼容性:TypeScript 的結(jié)構(gòu)化類型非常適合 JavaScript 動態(tài)和靈活的特性,使得與現(xiàn)有 JavaScript 代碼庫的集成更加容易。
  3. 減少樣板代碼:不需要顯式的接口或類型聲明,因為兼容性取決于結(jié)構(gòu),從而減少了樣板代碼。
  4. 增強代碼可重用性:結(jié)構(gòu)化類型允許具有兼容結(jié)構(gòu)的類型可以互換使用,促進了更模塊化和可維護的代碼。

ArkTS 不支持結(jié)構(gòu)化類型

了解了 TypeScript 是如何支持結(jié)構(gòu)化類型后,咱們就可以很好理解 ArkTS中不支持結(jié)構(gòu)化類型是什么意思了,那在 ArkTS中,不同對象是怎么兼容類型的呢?

在ArkTS中,對象的類型兼容性不是基于對象的結(jié)構(gòu)(如屬性和方法的集合)來確定的,而是基于接口或類的名義類型系統(tǒng)。

所以,如果兩個對象沒有實現(xiàn)相同的接口或繼承自相同的類,即使它們具有相同的公共API,它們也被視為完全不同的類型?。

在ArkTS中,對象的類型兼容性是基于接口或類的名義類型系統(tǒng)(Nominal Typing System),而不是基于對象的結(jié)構(gòu)(如屬性和方法的集合)來確定的。這意味著,只有當(dāng)一個對象的類型與另一個類型完全相同時,它們才被認為是兼容的。這與結(jié)構(gòu)化類型系統(tǒng)(Structural Typing System),如TypeScript中所采用的,有所不同,在結(jié)構(gòu)化類型系統(tǒng)中,如果兩個對象具有相同的形狀(即相同的屬性和方法),它們就被認為是兼容的,即使它們的類型名稱不同。

代碼案例解釋

1. 類型兼容性基于接口或類的聲明

在ArkTS中,如果有兩個類,即使它們的屬性和方法相同,但如果它們沒有相同的類聲明,它們將不被認為是兼容的。

// 定義兩個類,它們具有相同的屬性和方法
class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log(`The animal says something.`);
    }
}


class Dog {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    speak() {
        console.log(`Woof woof!`);
    }
}


// 在結(jié)構(gòu)化類型系統(tǒng)中,以下賦值是允許的,因為兩個對象具有相同的形狀
// let animal: Animal = new Dog(); // 錯誤,在ArkTS中不允許


// 在ArkTS中,上述賦值將導(dǎo)致錯誤,因為Animal和Dog是不同的類,即使它們具有相同的屬性和方法。

2. 接口之間的兼容性

在ArkTS中,接口之間的兼容性也是基于名義類型系統(tǒng)的。即使兩個接口具有相同的屬性和方法,它們也被認為是不同的類型。

// 定義兩個接口,它們具有相同的屬性和方法
interface IFly {
    fly(): void;
}


interface IBird {
    fly(): void;
}


// 在結(jié)構(gòu)化類型系統(tǒng)中,以下賦值是允許的,因為兩個接口具有相同的形狀
// let flyObject: IFly = { fly: () => console.log("Flying") } as IBird; // 錯誤,在ArkTS中不允許


// 在ArkTS中,上述賦值將導(dǎo)致錯誤,因為IFly和IBird是不同的接口,即使它們具有相同的方法。

3. 類和接口之間的兼容性

在ArkTS中,類可以實現(xiàn)接口,但類和接口之間的兼容性是基于名義類型系統(tǒng)的。

// 定義一個接口
interface IPrint {
    print(): void;
}


// 定義一個類,實現(xiàn)上述接口
class Printer implements IPrint {
    print(): void {
        console.log("Printing...");
    }
}


// 在ArkTS中,即使Printer實現(xiàn)了IPrint接口,它們也被認為是不同的類型。
// let printObject: IPrint = new Printer(); // 正確


// 但是,如果嘗試將IPrint賦值給Printer類型,將導(dǎo)致錯誤。
// let printerObject: Printer = { print: () => console.log("Printing") } as IPrint; // 錯誤

再強調(diào)一下,在ArkTS中,類型兼容性是基于接口或類的名義類型系統(tǒng),而不是基于對象的結(jié)構(gòu)。這意味著,只有當(dāng)兩個類型的聲明完全相同時,它們才被認為是兼容的。這與TypeScript中基于結(jié)構(gòu)的類型兼容性形成了對比。

那為什么 ArkTS 會不支持結(jié)構(gòu)化類型呢,V 哥的分析應(yīng)該是考慮以下幾個方面:

  1. 潛在的意外兼容性:在結(jié)構(gòu)化類型下,即使概念上不同,類型也可能被認為是兼容的,這可能導(dǎo)致錯誤。
  2. 有限的反射:TypeScript 沒有支持反射,這意味著程序員不能使用結(jié)構(gòu)進行運行時類型檢查。
  3. 類型安全與靈活性:結(jié)構(gòu)化類型提供了靈活性,但如果開發(fā)者不完全理解其含義,可能會犧牲類型安全。
  4. 調(diào)試復(fù)雜性:由于類型兼容性的隱式性質(zhì),調(diào)試可能更加困難,難以追蹤和修復(fù)問題。
  5. 性能考慮?:在某些情況下,名義類型系統(tǒng)可能在運行時具有更好的性能,因為它們可以在編譯時進行更多的檢查?.

最后

輸入圖片說明 不管官網(wǎng)是基于怎樣的考慮,華為的大佬們應(yīng)該是做充分的思考后的決定,當(dāng)然也沒有說死,后續(xù)會根據(jù)實際場景和反饋,看否是重新啟用結(jié)構(gòu)化類型,好了,到此你應(yīng)該可以完全理解了,歡迎關(guān)注威哥愛編程,鴻蒙開天辟地,你我相伴同行。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號