TypeScript?聲明合并的具體使用
在 TypeScript 的類型系統(tǒng)中,聲明合并是一個非常獨特且強大的特性,它讓多個同名的聲明可以被自動合并成一個統(tǒng)一的聲明結(jié)構(gòu)。這種機制不僅在使用現(xiàn)有 JavaScript 庫時非常有用,也為構(gòu)建復(fù)雜的類型抽象提供了便利。
本文將詳細介紹聲明合并的基本概念、常見形式、合并規(guī)則、限制,以及對你可能關(guān)心的問題如 interface
和 type
的同名情況進行探討。
一、什么是聲明合并?
聲明合并(Declaration Merging)是指:當 TypeScript 編譯器遇到多個同名的聲明時,會將它們合并為一個聲明,最終這個合并聲明具備所有原始聲明的特性。
簡而言之,就是多個同名聲明 → 一個完整的復(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ù)成員,名稱相同但類型不同會報錯。
- 如果是函數(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)先
當函數(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)合并
多個同名的 namespace
可以合并,其成員最終被聚合為一個命名空間:
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; // ? 報錯 } }
四、模塊與全局聲明擴展(Augmentation)
模塊擴展(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>; } }
不能新增頂級聲明,只能擴展現(xiàn)有結(jié)構(gòu),且僅支持具名導(dǎo)出。
全局擴展(Global Augmentation)
declare global { interface Array<T> { toObservable(): Observable<T>; } }
五、命名空間與其他類型合并
TypeScript 支持將命名空間與某些其他類型進行合并,常見于表達“內(nèi)部類”、“靜態(tài)成員擴展”等高級模式。
1. 命名空間 + 類(class)
class Album { label: Album.Label; } namespace Album { export class Label {} }
現(xiàn)在 Album.Label
是一個合法的引用。
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 }; // ? 報錯:重復(fù)標識符 "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)中的一項核心機制,熟練掌握它不僅可以更好地使用第三方類型定義,還能讓我們構(gòu)建更強大、靈活的類型表達。
八、參考資料
到此這篇關(guān)于TypeScript 聲明合并的具體使用的文章就介紹到這了,更多相關(guān)TypeScript 聲明合并內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序 scroll-view實現(xiàn)錨點滑動的示例
本篇文章主要介紹了微信小程序 scroll-view實現(xiàn)錨點滑動的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12uniapp使用navigateBack方法返回上級頁面并刷新的簡單示例
最近寫uniapp項目的時候發(fā)現(xiàn)有時候需要更新頁面數(shù)據(jù),所以下面這篇文章主要給大家介紹了關(guān)于uniapp使用navigateBack方法返回上級頁面并刷新的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-03-03深入淺析JavaScript系列(13):This? Yes,this!
在這篇文章里,我們將討論跟執(zhí)行上下文直接相關(guān)的更多細節(jié)。討論的主題就是this關(guān)鍵字。實踐證明,這個主題很難,在不同執(zhí)行上下文中this的確定經(jīng)常會發(fā)生問題2016-01-01用Javascript判斷圖片是否存在,不存在則顯示默認圖片的代碼
用Javascript判斷圖片是否存在,不存在則顯示默認圖片的代碼,需要的朋友可以參考下。2007-03-03查詢綁定數(shù)據(jù)島的表格中的文本并修改顯示方式的js代碼
查詢綁定數(shù)據(jù)島的表格中的文本并修改顯示方式的js代碼2009-12-12