TypeScript?聲明合并的具體使用
在 TypeScript 的類型系統(tǒng)中,聲明合并是一個(gè)非常獨(dú)特且強(qiáng)大的特性,它讓多個(gè)同名的聲明可以被自動(dòng)合并成一個(gè)統(tǒng)一的聲明結(jié)構(gòu)。這種機(jī)制不僅在使用現(xiàn)有 JavaScript 庫時(shí)非常有用,也為構(gòu)建復(fù)雜的類型抽象提供了便利。
本文將詳細(xì)介紹聲明合并的基本概念、常見形式、合并規(guī)則、限制,以及對你可能關(guān)心的問題如 interface 和 type 的同名情況進(jìn)行探討。
一、什么是聲明合并?
聲明合并(Declaration Merging)是指:當(dāng) TypeScript 編譯器遇到多個(gè)同名的聲明時(shí),會(huì)將它們合并為一個(gè)聲明,最終這個(gè)合并聲明具備所有原始聲明的特性。
簡而言之,就是多個(gè)同名聲明 → 一個(gè)完整的復(fù)合聲明。
二、接口(Interface)合并
最常見的合并形式就是接口合并。
interface Box {
height: number;
width: number;
}
interface Box {
scale: number;
}
const box: Box = { height: 10, width: 20, scale: 1.5 };
合并結(jié)果為:
interface Box {
height: number;
width: number;
scale: number;
}
?? 成員沖突規(guī)則
- 如果是非函數(shù)成員,名稱相同但類型不同會(huì)報(bào)錯(cuò)。
- 如果是函數(shù)成員,將作為函數(shù)重載合并,后聲明的排在前面。
interface Cloner {
clone(animal: Animal): Animal;
}
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}
合并結(jié)果:
interface Cloner {
clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Animal): Animal;
}
?? 字面量類型優(yōu)先
當(dāng)函數(shù)參數(shù)是單一字符串字面量時(shí),重載將被“提升”至重載列表頂部:
interface Document {
createElement(tagName: any): Element;
}
interface Document {
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {
createElement(tagName: string): HTMLElement;
createElement(tagName: "canvas"): HTMLCanvasElement;
}
合并結(jié)果:
interface Document {
createElement(tagName: "canvas"): HTMLCanvasElement;
createElement(tagName: "div"): HTMLDivElement;
createElement(tagName: "span"): HTMLSpanElement;
createElement(tagName: string): HTMLElement;
createElement(tagName: any): Element;
}
三、命名空間(Namespace)合并
多個(gè)同名的 namespace 可以合并,其成員最終被聚合為一個(gè)命名空間:
namespace Animals {
export class Dog {}
}
namespace Animals {
export interface Legged {
numberOfLegs: number;
}
}
合并結(jié)果為:
namespace Animals {
export class Dog {}
export interface Legged {
numberOfLegs: number;
}
}
? 非導(dǎo)出成員不可見
namespace Animal {
let hidden = true;
export function canSeeHidden() {
return hidden; // ? OK
}
}
namespace Animal {
export function tryToAccessHidden() {
return hidden; // ? 報(bào)錯(cuò)
}
}
四、模塊與全局聲明擴(kuò)展(Augmentation)
模塊擴(kuò)展(Module Augmentation)
// observable.ts
export class Observable<T> {}
// map.ts
import { Observable } from './observable';
declare module './observable' {
interface Observable<T> {
map<U>(fn: (x: T) => U): Observable<U>;
}
}
不能新增頂級(jí)聲明,只能擴(kuò)展現(xiàn)有結(jié)構(gòu),且僅支持具名導(dǎo)出。
全局?jǐn)U展(Global Augmentation)
declare global {
interface Array<T> {
toObservable(): Observable<T>;
}
}
五、命名空間與其他類型合并
TypeScript 支持將命名空間與某些其他類型進(jìn)行合并,常見于表達(dá)“內(nèi)部類”、“靜態(tài)成員擴(kuò)展”等高級(jí)模式。
1. 命名空間 + 類(class)
class Album {
label: Album.Label;
}
namespace Album {
export class Label {}
}
現(xiàn)在 Album.Label 是一個(gè)合法的引用。
2. 命名空間 + 函數(shù)(function)
function buildLabel(name: string): string {
return buildLabel.prefix + name + buildLabel.suffix;
}
namespace buildLabel {
export let prefix = "Hello, ";
export let suffix = "!";
}
支持 buildLabel("TypeScript") 與 buildLabel.prefix 等調(diào)用。
3. 命名空間 + 枚舉(enum)
enum Color {
Red = 1,
Green = 2,
}
namespace Color {
export function mix(): number {
return Color.Red + Color.Green;
}
}
這樣我們就可以使用 Color.mix() 作為枚舉的“靜態(tài)方法”。
六、type alias 與 interface 能否合并?
這是許多開發(fā)者關(guān)心的問題:TypeScript 不支持 type 與 interface 同名合并。
interface Foo {
x: number;
}
type Foo = { y: number }; // ? 報(bào)錯(cuò):重復(fù)標(biāo)識(shí)符 "Foo"
目前為止,interface 與 interface 可以合并,namespace 與其他部分類型也可以合并,但 type 與 interface 屬于不同的結(jié)構(gòu),不能合并。
七、總結(jié)
| 合并類型 | 是否支持 |
|---|---|
| interface 與 interface | ? |
| namespace 與 namespace | ? |
| namespace 與 class | ? |
| namespace 與 function | ? |
| namespace 與 enum | ? |
| type alias 與 interface | ? |
| class 與 class | ? |
| class 與 variable | ? |
聲明合并是 TypeScript 類型系統(tǒng)中的一項(xiàng)核心機(jī)制,熟練掌握它不僅可以更好地使用第三方類型定義,還能讓我們構(gòu)建更強(qiáng)大、靈活的類型表達(dá)。
八、參考資料
到此這篇關(guān)于TypeScript 聲明合并的具體使用的文章就介紹到這了,更多相關(guān)TypeScript 聲明合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS繪圖Flot如何實(shí)現(xiàn)動(dòng)態(tài)可刷新曲線圖
這篇文章主要介紹了JS繪圖Flot如何實(shí)現(xiàn)動(dòng)態(tài)可刷新曲線圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Display SQL Server Version Information
Display SQL Server Version Information...2007-06-06
javascript實(shí)現(xiàn)TreeView 無刷新展開的實(shí)例代碼
這篇文章介紹了javascript實(shí)現(xiàn)TreeView 無刷新展開的實(shí)例代碼,有需要的朋友可以參考一下2013-07-07
JavaScript實(shí)現(xiàn)的拼圖算法分析
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的拼圖算法,結(jié)合實(shí)例形式分析了javascript圖形拼接與判定算法相關(guān)操作技巧及注意事項(xiàng),需要的朋友可以參考下2019-02-02
JS實(shí)現(xiàn)鍵值對遍歷json數(shù)組功能示例
這篇文章主要介紹了JS實(shí)現(xiàn)鍵值對遍歷json數(shù)組功能,結(jié)合實(shí)例形式分析了javascript遍歷json數(shù)組相關(guān)操作技巧,需要的朋友可以參考下2018-05-05

