最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

TypeScript聲明合并的多種使用方式

 更新時間:2026年05月12日 09:42:38   作者:吳聲子夜歌  
本文主要介紹了TypeScript聲明合并的多種使用方式,包括接口聲明合并、枚舉聲明合并、類聲明合并、命名空間聲明合并、模塊擴充聲明和全局聲明擴充,感興趣的可以了解一下

聲明是編程語言中的基礎結(jié)構,它描述了一個標識符所表示的含義。在TypeScript語言中,一個標識符總共可以有以下三種含義:

  • 表示一個值。
  • 表示一個類型。
  • 表示一個命名空間。

下例中,我們分別定義了值、類型和命名空間。其中,常量zero屬于值,接口Point屬于類型,而命名空間Utils則屬于命名空間。示例如下:

const zero = 0;

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

namespace Utils {}

對于同一個標識符而言,它可以同時具有上述多種含義。例如,有一個標識符A,它可以同時表示一個值、一種類型和一個命名空間。示例如下:

const A = 0;

interface A {}

namespace A {}

在同一聲明空間內(nèi)使用的標識符必須唯一。TypeScript語言中的大部分語法結(jié)構都能夠創(chuàng)建出新的聲明空間,例如函數(shù)聲明和類聲明都能夠創(chuàng)建出一個新的聲明空間。最典型的聲明空間是全局聲明空間和模塊聲明空間。當編譯器發(fā)現(xiàn)同一聲明空間內(nèi)存在同名的聲明時,會嘗試將所有同名的聲明合并為一個聲明,即聲明合并;若發(fā)現(xiàn)無法進行聲明合并,則會產(chǎn)生編譯錯誤。聲明合并是TypeScript語言特有的行為。在進行聲明合并時,編譯器會按照標識符的含義進行分組合并,即值和值合并、類型和類型合并以及命名空間和命名空間合并。但是并非所有同名的聲明都允許進行聲明合并,例如,常量聲明a和函數(shù)聲明a之間不會進行聲明合并。

接下來,將具體介紹TypeScript語言中的聲明合并,包括接口聲明、枚舉聲明、類聲明、命名空間聲明、擴充模塊聲明、擴充全局聲明。

1、接口聲明合并

接口聲明為標識符定義了類型含義。在同一聲明空間內(nèi)聲明的多個同名接口會合并成一個接口聲明。下例中,存在兩個A接口聲明,它們屬于同一聲明空間。編譯器會將兩個A接口聲明中的類型成員合并到一起,合并后的接口A等同于接口MergedA。示例如下:

interface A {
    a: string;
}

interface A {
    b: number;
}

interface MergedA {
    a: string;
    b: number;
}

若待合并的接口中存在同名的屬性簽名類型成員,那么這些同名的屬性簽名必須是相同的類型,否則會因為合并沖突而產(chǎn)生編譯錯誤。例如,在下例的兩個接口A中,屬性成員a的類型分別為number類型和string類型,在合并接口時會發(fā)生沖突。示例如下:

interface A {
    a: number;
}

interface A {
    a: string; // 編譯錯誤
}

若待合并的接口中存在同名的方法簽名類型成員,那么同名的方法簽名類型成員會被視為函數(shù)重載,并且靠后定義的方法簽名具有更高的優(yōu)先級。例如,下例的兩個A接口聲明中都定義了方法簽名類型成員f。在合并后的接口A中,方法簽名f具有兩個重載簽名并且后聲明的f方法(第6行)具有更高的優(yōu)先級。示例如下:

interface A {
    f(x: any): void;
}

interface A {
    f(x: string): boolean;
}

interface MergedA {
    f(x: string): boolean;
    f(x: any): void;
}

合并重載簽名的基本原則是后聲明的重載簽名具有更高優(yōu)先級。但也存在一個例外,若重載簽名的參數(shù)類型中包含字面量類型,則該重載簽名具有更高的優(yōu)先級。例如,下例中盡管第2行的方法簽名f是先聲明的,但在接口合并后仍具有更高的優(yōu)先級,因為它的函數(shù)簽名中帶有字面量類型。示例如下:

interface A {
    f(x: 'foo'): boolean;
}

interface A {
    f(x: any): void;
}

interface MergedA {
    f(x: 'foo'): boolean;
    f(x: any): void;
}

若待合并的接口中存在多個調(diào)用簽名類型成員或構造簽名類型成員,那么它們將被視作函數(shù)重載和構造函數(shù)重載。與合并方法簽名類型成員相同,后聲明的調(diào)用簽名類型成員和構造簽名類型成員具有更高的優(yōu)先級,同時也會參考參數(shù)類型中是否包含字面量類型。示例如下:

interface A {
    new (x: any): object;
    (x: any): any;
}

interface A {
    new (x: string): Date;
    (x: string): string;
}

interface MergedA {
    new (x: string): Date;
    new (x: any): object;
    (x: string): string;
    (x: any): any;
}

當涉及重載時,接口合并的順序變得尤為重要,因為它將影響重載的解析順序。

若待合并的接口中存在多個字符串索引簽名或數(shù)值索引簽名,則將產(chǎn)生編譯錯誤。在合并接口時,所有的接口中只允許存在一個字符串索引簽名和一個數(shù)值索引簽名。示例如下:

interface A {
    [prop: string]: string;
}

interface A {
    [prop: number]: string;
}

interface MergedA {
    [prop: string]: string;
    [prop: number]: string;
}

若待合并的接口是泛型接口,那么所有同名接口必須有完全相同的類型參數(shù)列表。若待合并的接口存在繼承的接口,那么所有繼承的接口會被合并為單一的父接口。在實際程序中,我們應避免復雜接口的合并行為,因為這會讓代碼變得難以理解。

2、枚舉聲明合并

多個同名的枚舉聲明會合并成一個枚舉聲明。在合并枚舉聲明時,只允許其中一個枚舉聲明的首個枚舉成員省略初始值。示例如下:

enum E {
    A,
}

enum E {
    B = 1,
}

enum E {
    C = 2,
}

let e: E;
e = E.A;
e = E.B;
e = E.C;

此例中,第2行的首個枚舉成員省略了初始值,因此TypeScript會自動計算初始值。第6行和第10行,必須為首個枚舉成員定義初始值,否則將產(chǎn)生編譯錯誤,因為編譯器無法在多個同名枚舉聲明之間自動地計算枚舉值。

枚舉聲明合并的另外一點限制是,多個同名的枚舉聲明必須同時為const枚舉或非const枚舉,不允許混合使用。示例如下:

// 正確
enum E0 {
    A,
}
enum E0 {
    B = 1,
}

// 正確
const enum E1 {
    A,
}
const enum E1 {
    B = 1,
}

// 編譯錯誤
enum E2 {
    A,
}
const enum E2 {
    B = 1,
}

3、類聲明合并

TypeScript不支持合并同名的類聲明,但是外部類聲明可以與接口聲明進行合并,合并后的類型為類類型。示例如下:

declare class C {
    x: string;
}

interface C {
    y: number;
}

let c: C = new C();
c.x;
c.y;

4、命名空間聲明合并

命名空間的聲明合并會稍微復雜一些,它可以與命名空間、函數(shù)、類和枚舉進行合并。

4.1 命名空間與命名空間合并

與合并接口類似,同名的命名空間也會進行合并。例如,編譯器會將下例中的兩個Animals命名空間進行合并,合并后的命名空間等同于命名空間MergedAnimals。示例如下:

namespace Animals {
    export class Bird {}
}

namespace Animals {
    export interface CanFly {
        canFly: boolean;
    }
    export class Dog {}
}

namespace MergedAnimals {
    export interface CanFly {
        canFly: boolean;
    }
    export class Bird {}
    export class Dog {}
}

如果存在嵌套的命名空間,那么在合并外層命名空間時,同名的內(nèi)層命名空間也會進行合并。示例如下:

namespace outer {
    export namespace inner {
        export var x = 10;
    }
}
namespace outer {
    export namespace inner {
        export var y = 20;
    }
}

namespace MergedOuter {
    export namespace inner {
        export var x = 10;
        export var y = 20;
    }
}

在合并命名空間聲明時,命名空間中的非導出成員不會被合并,它們只能在各自的命名空間中使用。示例如下:

namespace NS {
    const a = 0;

    export function foo() {
        a;  // 正確
    }
}

namespace NS {
    export function bar() {
        foo(); // 正確

        a;  // 編譯錯誤:找不到 'a'
    }
}

4.2 命名空間與函數(shù)合并

同名的命名空間聲明與函數(shù)聲明可以進行合并,但是要求函數(shù)聲明必須位于命名空間聲明之前,這樣做能夠確保先創(chuàng)建出一個函數(shù)對象。函數(shù)與命名空間合并就相當于給函數(shù)對象添加額外的屬性。示例如下:

function f() {
    return f.version;
}

namespace f {
    export const version = '1.0';
}

f();   // '1.0'
f.version; // '1.0'

4.3 命名空間與類合并

同名的命名空間聲明與類聲明可以進行合并,但是要求類聲明必須位于命名空間聲明之前,這樣做能夠確保先創(chuàng)建出一個構造函數(shù)對象。命名空間與類的合并提供了一種創(chuàng)建內(nèi)部類的方式。示例如下:

class Outer {
    inner: Outer.Inner = new Outer.Inner();
}

namespace Outer {
    export class Inner {}
}

我們也可以利用命名空間與類的聲明合并來為類添加靜態(tài)屬性和方法。示例如下:

class A {
    foo: string = A.bar;
}

namespace A {
    export let bar = 'A';
    export function create() {
        return new A();
    }
}

const a: A = A.create();
a.foo; // 'A'
A.bar; // 'A'

4.4 命名空間與枚舉合并

同名的命名空間聲明與枚舉聲明可以進行合并。這相當于將枚舉成員與命名空間的導出成員進行合并。示例如下:

enum E {
    A,
    B,
    C,
}

namespace E {
    export function foo() {
        E.A;
        E.B;
        E.C;
    }
}

E.A;
E.B;
E.C;
E.foo();

需要注意的是,枚舉成員名與命名空間導出成員名不允許出現(xiàn)同名的情況。示例如下:

enum E {
    A,                     // 編譯錯誤!重復的標識符 A
}

namespace E {
    export function A() {} // 編譯錯誤!重復的標識符 A
}

5、擴充模塊聲明

對于任意模塊,通過模塊擴充語法能夠?qū)δK內(nèi)的已有聲明進行擴展。例如,在“a.ts”模塊中定義了一個接口A,在“b.ts”模塊中可以對“a.ts”模塊中定義的接口A進行擴展,為其增加新的屬性。

假設有如下目錄結(jié)構的工程:

C:\app
|-- a.ts
`-- b.ts

“a.ts”模塊文件的內(nèi)容如下:

export interface A {
    x: number;
}

“b.ts”模塊文件的內(nèi)容如下:

import { A } from './a';

declare module './a' {
    interface A {
        y: number;
    }
}

const a: A = { x: 0, y: 0 };

此例中,?“declare module ‘./a’ {}”是模塊擴充語法。其中,?“‘./a’”表示要擴充的模塊名,它與第一行模塊導入語句中的模塊名一致。

我們使用模塊擴充語法對導入模塊“‘./a’”進行了擴充。第4行定義的接口A將與“a.ts”模塊中的接口A進行聲明合并,合并后的結(jié)果仍為接口A,但是接口A增加了一個屬性成員y。

在進行模塊擴充時有以下兩點需要注意:

  • 不能在模塊擴充語法中增加新的頂層聲明,只能擴充現(xiàn)有的聲明。也就是說,我們只能對“‘./a’”模塊中已經(jīng)存在的接口A進行擴充,而不允許增加新的聲明,例如新定義一個接口B。
  • 無法使用模塊擴充語法對模塊的默認導出進行擴充,只能對命名模塊導出進行擴充,因為在進行模塊擴充時需要依賴于導出的名字。

6、擴充全局聲明

與模塊擴充類似,TypeScript還提供了全局對象擴充語法“declare global {}”?。示例如下:

export {};

declare global {
    interface Window {
        myAppConfig: object;
    }
}

const config: object = window.myAppConfig;

此例中,?“declare global {}”是全局對象擴充語法,它擴展了全局的Window對象,增加了一個myAppConfig屬性。第1行,我們使用了“export {}”空導出語句,這是因為全局對象擴充語句必須在模塊或外部模塊聲明中使用,當我們添加了空導出語句后,該文件就成了一個模塊。

全局對象擴充也具有和模塊擴充相同的限制,不能在全局對象擴充語法中增加新的頂層聲明,只能擴充現(xiàn)有的聲明。

到此這篇關于TypeScript聲明合并的多種使用方式的文章就介紹到這了,更多相關TypeScript聲明合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vim快速合并行及vim 將文件所有行合并到一行

    Vim快速合并行及vim 將文件所有行合并到一行

    Vim是一個類似于Vi的著名的功能強大、高度可定制的文本編輯器,在Vi的基礎上改進和增加了很多特性.這篇文章主要介紹了Vim快速合并行及vim 將文件所有行合并到一行,需要的朋友可以參考下
    2017-11-11
  • 深入理解JavaScript 參數(shù)按值傳遞

    深入理解JavaScript 參數(shù)按值傳遞

    本篇文章主要介紹了深入理解JavaScript 參數(shù)按值傳遞,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 用JS實現(xiàn)飛機大戰(zhàn)小游戲

    用JS實現(xiàn)飛機大戰(zhàn)小游戲

    這篇文章主要為大家詳細介紹了用JS實現(xiàn)飛機大戰(zhàn)小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 分離式javascript取當前element值的代碼

    分離式javascript取當前element值的代碼

    比較不錯的分離式js代碼,獲取element的值,大家注意下,運行后的效果是32之類的值,其實主要是沒有強制轉(zhuǎn)換成數(shù)字,所以大家可以加上
    2008-05-05
  • HTML+JavaScript實現(xiàn)筋斗云導航欄效果

    HTML+JavaScript實現(xiàn)筋斗云導航欄效果

    這篇文章主要為大家介紹了如何利用HTML+JavaScript+CSS實現(xiàn)筋斗云導航欄效果,當鼠標經(jīng)過某個li,筋斗云跟著到當前的位置,感興趣的小伙伴可以試一試
    2022-03-03
  • Bootstrap按鈕下拉菜單組件詳解

    Bootstrap按鈕下拉菜單組件詳解

    這篇文章主要為大家詳細介紹了Bootstrap按鈕下拉菜單組件,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 原生JS實現(xiàn)百葉窗特效

    原生JS實現(xiàn)百葉窗特效

    這篇文章主要為大家詳細介紹了原生JS實現(xiàn)百葉窗特效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • JavaScript實現(xiàn)動態(tài)生成表格

    JavaScript實現(xiàn)動態(tài)生成表格

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)動態(tài)生成表格,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • BootStrap輪播HTML代碼(推薦)

    BootStrap輪播HTML代碼(推薦)

    本文給大家分享bootstrap輪播h tml代碼,代碼簡單易懂非常不錯,具有參考借鑒,需要的朋友參考下吧
    2016-12-12
  • JavaScript DOM節(jié)點操作方法總結(jié)

    JavaScript DOM節(jié)點操作方法總結(jié)

    下面小編就為大家?guī)硪黄狫avaScript DOM節(jié)點操作方法總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08

最新評論

尚志市| 白银市| 绵竹市| 桐梓县| 宜宾市| 永嘉县| 南通市| 莱西市| 旬阳县| 彰武县| 遂平县| 庄河市| 溧阳市| 明溪县| 潢川县| 兴文县| 红原县| 英吉沙县| 池州市| 丹江口市| 鹤岗市| 阿鲁科尔沁旗| 专栏| 察哈| 巴塘县| 荆门市| 平果县| 江川县| 徐水县| 德保县| 巴楚县| 景德镇市| 镇雄县| 清徐县| 兰西县| 黄石市| 城口县| 志丹县| 仁化县| 温泉县| 吉水县|