日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何在TypeScript中使用命名空間

介紹

TypeScript 是 JavaScript 語言的擴展,它使用 JavaScript 運行時和編譯時類型檢查器。

專注于為中小企業(yè)提供成都做網(wǎng)站、網(wǎng)站設(shè)計服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)嶧城免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。

TypeScript 提供了多種方法來表示代碼中的對象,其中一種是使用接口。 TypeScript 中的接口有兩種使用場景:您可以創(chuàng)建類必須遵循的約定,例如,這些類必須實現(xiàn)的成員,還可以在應(yīng)用程序中表示類型,就像普通的類型聲明一樣。 

您可能會注意到接口和類型共享一組相似的功能。

事實上,一個幾乎總是可以替代另一個。

主要區(qū)別在于接口可能對同一個接口有多個聲明,TypeScript 將合并這些聲明,而類型只能聲明一次。您還可以使用類型來創(chuàng)建原始類型(例如字符串和布爾值)的別名,這是接口無法做到的。

TypeScript 中的接口是表示類型結(jié)構(gòu)的強大方法。它們允許您以類型安全的方式使用這些結(jié)構(gòu)并同時記錄它們,從而直接改善開發(fā)人員體驗。

在今天的文章中,我們將在 TypeScript 中創(chuàng)建接口,學(xué)習(xí)如何使用它們,并了解普通類型和接口之間的區(qū)別。

我們將嘗試不同的代碼示例,可以在 TypeScript 環(huán)境或 TypeScript Playground(一個允許您直接在瀏覽器中編寫 TypeScript 的在線環(huán)境)中遵循這些示例。

準(zhǔn)備工作

要完成今天的示例,我們將需要做如下準(zhǔn)備工作:

  • 一個環(huán)境。我們可以執(zhí)行 TypeScript 程序以跟隨示例。要在本地計算機上進行設(shè)置,我們將需要準(zhǔn)備以下內(nèi)容。
  1. 為了運行處理 TypeScript 相關(guān)包的開發(fā)環(huán)境,同時安裝了 Node 和 npm(或 yarn)。本文教程中使用 Node.js 版本 為14.3.0 和 npm 版本 6.14.5 進行了測試。要在 macOS 或 Ubuntu 18.04 上安裝,請按照如何在 macOS 上安裝 Node.js 和創(chuàng)建本地開發(fā)環(huán)境或如何在 Ubuntu 18.04 上安裝 Node.js 的使用 PPA 安裝部分中的步驟進行操作。如果您使用的是適用于 Linux 的 Windows 子系統(tǒng) (WSL),這也適用。
  2. 此外,我們需要在機器上安裝 TypeScript 編譯器 (tsc)。為此,請參閱官方 TypeScript 網(wǎng)站。
  • 如果你不想在本地機器上創(chuàng)建 TypeScript 環(huán)境,你可以使用官方的 TypeScript Playground 來跟隨。
  • 您將需要足夠的 JavaScript 知識,尤其是 ES6+ 語法,例如解構(gòu)、rest 運算符和導(dǎo)入/導(dǎo)出。如果您需要有關(guān)這些主題的更多信息,建議閱讀我們的如何用 JavaScript 編寫代碼系列。
  • 本文教程將參考支持 TypeScript 并顯示內(nèi)聯(lián)錯誤的文本編輯器的各個方面。這不是使用 TypeScript 所必需的,但確實可以更多地利用 TypeScript 功能。為了獲得這些好處,您可以使用像 Visual Studio Code 這樣的文本編輯器,它完全支持開箱即用的 TypeScript。你也可以在 TypeScript Playground 中嘗試這些好處。

本教程中顯示的所有示例都是使用 TypeScript 4.2.2 版創(chuàng)建的。

在 TypeScript 中創(chuàng)建命名空間

在本節(jié)中,我們將一起來學(xué)習(xí)在 TypeScript 中創(chuàng)建命名空間以說明一般語法。

要創(chuàng)建命名空間,我們將使用命名空間關(guān)鍵字,后跟命名空間的名稱,然后是 {} 塊。 

例如,我們將創(chuàng)建一個 DatabaseEntity 命名空間來保存數(shù)據(jù)庫實體,就像我們使用對象關(guān)系映射 (ORM) 庫一樣。 

將以下代碼添加到新的 TypeScript 文件中:

namespace DatabaseEntity {
}

這聲明了 DatabaseEntity 命名空間,但尚未向該命名空間添加代碼。 接下來,在命名空間中添加一個 User 類來表示數(shù)據(jù)庫中的一個 User 實體:

namespace DatabaseEntity {
class User {
constructor(public name: string) {}
}
}

我們可以在命名空間中正常使用 User 類。 為了說明這一點,創(chuàng)建一個新的 User 實例并將其存儲在 newUser 變量中:

namespace DatabaseEntity {
class User {
constructor(public name: string) {}
}

const newUser = new User("Jon");
}

這是有效的代碼。 

但是,如果我們嘗試在命名空間之外使用 User,TypeScript 編譯器會給我們返回錯誤 2339:

Out
putProperty 'User' does not exist on type 'typeof DatabaseEntity'. (2339)

如果我們想在命名空間之外使用類,則必須首先導(dǎo)出 User 類以在外部可用,如下面突出顯示的代碼所示:

namespace DatabaseEntity {
exportclass User {
constructor(public name: string) {}
}

const newUser = new User("Jon");
}

我們現(xiàn)在可以使用完全限定名稱訪問 DatabaseEntity 命名空間之外的 User 類。 在這種情況下,完全限定名稱是 DatabaseEntity.User:


namespace DatabaseEntity {
export class User {
constructor(public name: string) {}
}

const newUser = new User("Jon");
}

const newUserOutsideNamespace = new DatabaseEntity.User("Jane");

我們可以從命名空間中導(dǎo)出任何內(nèi)容,包括變量,然后這些變量將成為命名空間中的屬性。 

在以下代碼中,我們將導(dǎo)出 newUser 變量:

namespace DatabaseEntity {
export class User {
constructor(public name: string) {}
}

exportconst newUser = new User("Jon");
}

console.log(DatabaseEntity.newUser.name);

由于變量 newUser 已導(dǎo)出,因此,我們可以將其作為命名空間的屬性進行訪問。 運行此代碼會將以下內(nèi)容打印到控制臺:

Output
Jon

就像接口一樣,TypeScript 中的命名空間也允許聲明合并。 這意味著同一命名空間的多個聲明將合并為一個聲明。 如果我們需要稍后在代碼中擴展命名空間,這可以增加命名空間的靈活性。

使用前面的示例,這意味著如果我們再次聲明 DatabaseEntity 命名空間,我們將能夠使用更多屬性擴展命名空間。 使用另一個命名空間聲明將一個新類 UserRole 添加到我們的 DatabaseEntity 命名空間:

namespace DatabaseEntity {
export class User {
constructor(public name: string) {}
}

export const newUser = new User("Jon");
}

namespace DatabaseEntity {
export class UserRole {
constructor(public user: User, public role: string) {}
}

export const newUserRole = new UserRole(newUser, "admin");
}

在新的 DatabaseEntity 命名空間聲明中,我們可以使用以前在 DatabaseEntity 命名空間中導(dǎo)出的任何成員,包括從以前的聲明中導(dǎo)出的成員,而不必使用它們的完全限定名。

我們正在使用在第一個命名空間中聲明的名稱來將 UserRole 構(gòu)造函數(shù)中的用戶參數(shù)的類型設(shè)置為 User 類型,并在使用 newUser 值創(chuàng)建新的 UserRole 實例時。這僅是可能的,因為,我們在之前的命名空間聲明中導(dǎo)出了這些內(nèi)容。

現(xiàn)在,我們已經(jīng)了解了命名空間的基本語法,我們可以繼續(xù)研究 TypeScript 編譯器如何將命名空間轉(zhuǎn)換為 JavaScript。

檢查使用命名空間時生成的 JavaScript 代碼

TypeScript 中的命名空間不僅僅是一個編譯時特性。他們還更改了生成的 JavaScript 代碼。要了解有關(guān)命名空間如何工作的更多信息,我們可以分析支持此 TypeScript 功能的 JavaScript。

在這一步中,我們將獲取上一節(jié)中的代碼片段并檢查它們的底層 JavaScript 實現(xiàn)。

以我們在第一個示例中使用的代碼為例:

namespace DatabaseEntity {
export class User {
constructor(public name: string) {}
}

export const newUser = new User("Jon");
}

console.log(DatabaseEntity.newUser.name);

TypeScript 編譯器會為此 TypeScript 片段生成以下 JavaScript 代碼:

"use strict";
var DatabaseEntity;
(function (DatabaseEntity) {
class User {
constructor(name) {
this.name = name;
}
}
DatabaseEntity.User = User;
DatabaseEntity.newUser = new User("Jon");
})(DatabaseEntity || (DatabaseEntity = {}));
console.log(DatabaseEntity.newUser.name);

為了聲明 DatabaseEntity 命名空間,TypeScript 編譯器創(chuàng)建一個名為 DatabaseEntity 的未初始化變量,然后,創(chuàng)建一個立即調(diào)用函數(shù)表達(dá)式 (IIFE)。 此 IIFE 接收單個參數(shù) DatabaseEntity || (DatabaseEntity = {}),這是 DatabaseEntity 變量的當(dāng)前值。 如果未設(shè)置為真值,則將變量的值設(shè)置為空對象。

在將 DatabaseEntity 的值傳遞給 IIFE 時將其設(shè)置為空值是可行的,因為賦值操作的返回值是被賦值的值。 在這種情況下,這是空對象。

在 IIFE 內(nèi)部,創(chuàng)建了 User 類,然后,將其分配給 DatabaseEntity 對象的 User 屬性。 newUser 屬性也是如此,我們將屬性分配給新 User 實例的值。

現(xiàn)在看一下第二個代碼示例,其中有多個命名空間聲明:


namespace DatabaseEntity {
export class User {
constructor(public name: string) {}
}

export const newUser = new User("Jon");
}

namespace DatabaseEntity {
export class UserRole {
constructor(public user: User, public role: string) {}
}

export const newUserRole = new UserRole(newUser, "admin");
}

生成的 JavaScript 代碼如下所示:?

"use strict";
var DatabaseEntity;
(function (DatabaseEntity) {
class User {
constructor(name) {
this.name = name;
}
}
DatabaseEntity.User = User;
DatabaseEntity.newUser = new User("Jon");
})(DatabaseEntity || (DatabaseEntity = {}));
(function (DatabaseEntity) {
class UserRole {
constructor(user, role) {
this.user = user;
this.role = role;
}
}
DatabaseEntity.UserRole = UserRole;
DatabaseEntity.newUserRole = new UserRole(DatabaseEntity.newUser, "admin");
})(DatabaseEntity || (DatabaseEntity = {}));

代碼的開頭看起來與之前的相同,未初始化的變量 DatabaseEntity,然后是一個 IIFE,其中實際代碼設(shè)置了 DatabaseEntity 對象的屬性。這一次,雖然,還有另一個 IIFE。這個新的 IIFE 與 DatabaseEntity 命名空間的第二個聲明相匹配。

現(xiàn)在,當(dāng)執(zhí)行第二個 IIFE 時,DatabaseEntity 已經(jīng)綁定到一個對象,因此,我們只是通過添加額外屬性來擴展已經(jīng)可用的對象。

我們現(xiàn)在已經(jīng)了解了 TypeScript 命名空間的語法以及它們在底層 JavaScript 中的工作方式。有了這個上下文,我們現(xiàn)在可以運行命名空間的一個常見用例:為外部庫定義類型而無需鍵入。

使用命名空間為外部庫提供類型

在這部分內(nèi)容中,我們將體驗命名空間有用的場景之一:為外部庫創(chuàng)建模塊聲明。為此,我們將在 TypeScript 項目中編寫一個新文件來聲明類型,然后更改 tsconfig.json 文件以使 TypeScript 編譯器識別類型。

注意:要執(zhí)行后續(xù)步驟,需要一個可以訪問文件系統(tǒng)的 TypeScript 環(huán)境。如果您使用的是 TypeScript Playground,則可以通過單擊頂部菜單中的導(dǎo)出,然后在 CodeSandbox 中打開,將現(xiàn)有代碼導(dǎo)出到 CodeSandbox 項目。這將允許您創(chuàng)建新文件并編輯 tsconfig.json 文件。

并非 npm 注冊表中的每個可用包都捆綁了自己的 TypeScript 模塊聲明。這意味著在項目中安裝包時,您可能會遇到與包缺少類型聲明相關(guān)的編譯錯誤,或者必須使用所有類型都設(shè)置為 any 的庫。根據(jù)您使用 TypeScript 的嚴(yán)格程度,這可能是一個不希望的結(jié)果。

希望這個包將有一個由 DefinetelyTyped 社區(qū)創(chuàng)建的 @types 包,允許您安裝包并獲得該庫的工作類型。

但是,情況并非總是如此,有時您必須處理一個不捆綁其自己的類型模塊聲明的庫。在這種情況下,如果您想保持您的代碼完全類型安全,您必須自己創(chuàng)建模塊聲明。

例如,假設(shè)您正在使用一個名為 example-vector3 的向量庫,它使用單個方法 add 導(dǎo)出單個類 Vector3。此方法用于將兩個 Vector3 向量相加。

庫中的代碼可能如下所示:


export class Vector3 {
super(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}

add(vec) {
let x = this.x + vector.x;
let y = this.y + vector.y;
let z = this.z + vector.z;

let newVector = new Vector3(x, y, z);

return newVector
}
}

這導(dǎo)出了一個類,該類創(chuàng)建具有 x、y 和 z 屬性的向量,用于表示向量的坐標(biāo)分量。

接下來,看一下使用假設(shè)庫的示例代碼:

index.ts

import { Vector3 } from "example-vector3";

const v1 = new Vector3(1, 2, 3);
const v2 = new Vector3(1, 2, 3);

const v3 = v1.add(v2);

example-vector3 庫沒有與它自己的類型聲明捆綁在一起,因此, TypeScript 編譯器將給出錯誤 2307:

Output
Cannot find module 'example-vector3' or its corresponding type declarations. ts(2307)

為了解決這個問題,我們現(xiàn)在將為這個包創(chuàng)建一個類型聲明文件。 

首先,創(chuàng)建一個名為 types/example-vector3/index.d.ts 的新文件。

然后,在您喜歡的編輯器中打開它。 

在此文件中寫入以下代碼:

declare module "example-vector3" {
export = vector3;

namespace vector3 {
}
}

在此代碼中,我們正在為 example-vector3 模塊創(chuàng)建類型聲明。 代碼的第一部分是聲明模塊塊本身。 TypeScript 編譯器將解析這個塊并解釋其中的所有內(nèi)容,就好像它是模塊本身的類型表示一樣。 這意味著我們在此處聲明的任何內(nèi)容,TypeScript 都將用于推斷模塊的類型。 

現(xiàn)在,您說這個模塊導(dǎo)出了一個名為 vector3 的命名空間,該命名空間目前是空的。

保存并退出此文件。

TypeScript 編譯器當(dāng)前不知道您的聲明文件,因此您必須將其包含在您的 tsconfig.json 中。 

為此,通過將 types 屬性添加到 compilerOptions 選項來編輯項目 tsconfig.json:

{
"compilerOptions": {
...
"types": ["./types/example-vector3/index.d.ts"]
}
}

現(xiàn)在,如果我們返回原始代碼,我們將看到錯誤已更改。TypeScript 編譯器現(xiàn)在給出錯誤是2305:

Output
Module '"example-vector3"' has no exported member 'Vector3'. ts(2305)

當(dāng)我們?yōu)?example-vector3 創(chuàng)建模塊聲明時,導(dǎo)出當(dāng)前設(shè)置為空命名空間。 沒有從該命名空間中導(dǎo)出 Vector3 類。

重新打開 types/example-vector3/index.d.ts 并編寫以下代碼:


declare module "example-vector3" {
export = vector3;

namespace vector3 {
export class Vector3 {
constructor(x: number, y: number, z: number);
add(vec: Vector3): Vector3;
}
}
}

在此代碼中,請注意,我們現(xiàn)在如何在 vector3 命名空間內(nèi)導(dǎo)出一個類。模塊聲明的主要目標(biāo)是提供由庫公開的值的類型信息。這樣,我們可以以類型安全的方式使用它。

在這種情況下,我們知道 example-vector3 庫提供了一個名為 Vector3 的類,該類在構(gòu)造函數(shù)中接受三個數(shù)字,并且具有用于將兩個 Vector3 實例相加的 add 方法,并返回一個新實例作為結(jié)果。

我們無需在此處提供實現(xiàn),只需提供類型信息本身。不提供實現(xiàn)的聲明在 TypeScript 中稱為環(huán)境聲明,通常在 .d.ts 文件中創(chuàng)建這些聲明。

此代碼現(xiàn)在將正確編譯并具有 Vector3 類的正確類型。

使用命名空間,我們可以將庫導(dǎo)出的內(nèi)容隔離到單個類型單元中,在本例中為 vector3 命名空間。這使得自定義模塊聲明變得更加容易,甚至可以通過將類型聲明提交到 DefinetelyTyped 存儲庫來使所有開發(fā)人員都可以使用它。

最后結(jié)論

在今天的教程中,我們了解了 TypeScript 中命名空間的基本語法,并檢查了 TypeScript 編譯器將其更改為的 JavaScript。

我們還嘗試了命名空間的一個常見用例:為尚未鍵入的外部庫提供環(huán)境類型。

雖然,不推薦使用命名空間,但并不總是建議在代碼庫中使用命名空間作為代碼組織機制?,F(xiàn)代代碼應(yīng)該使用 ES 模塊語法,因為它具有命名空間提供的所有功能,并且從 ECMAScript 2015 開始,它成為規(guī)范的一部分。

但是,在創(chuàng)建模塊聲明時,仍然建議使用命名空間,因為它允許更簡潔的類型聲明。

如果你還想閱讀更多有關(guān) TypeScript 的教程文章,請看下面的推薦閱讀內(nèi)容,如果你覺得我今天的教程不錯,請點贊我,關(guān)注我,并將這篇文章分享給你的朋友,也許能夠幫助到他。

最后,感謝你的閱讀,編程快樂!


分享標(biāo)題:如何在TypeScript中使用命名空間
地址分享:http://www.dlmjj.cn/article/cojeihi.html