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

TypeScript實(shí)現(xiàn)可調(diào)用接口與構(gòu)造簽名

 更新時(shí)間:2026年05月13日 09:01:20   作者:燭銜溟  
本文深入探討TypeScript中可調(diào)用接口的進(jìn)階用法,幫助開發(fā)者描述復(fù)雜函數(shù)形態(tài),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、可調(diào)用接口(Callable Interface)

1.1 為什么需要可調(diào)用接口

之前學(xué)過函數(shù)類型表達(dá)式(如 type Fn = (a: number) => number),可以描述一個(gè)函數(shù)的形狀。但當(dāng)函數(shù)本身還帶有屬性(如 fn.defaultValue = 0),或者需要描述具有多種調(diào)用方式的重載函數(shù)時(shí),函數(shù)類型表達(dá)式就不夠用了。

可調(diào)用接口通過在接口中定義調(diào)用簽名(call signature)來描述函數(shù)類型。

1.2 調(diào)用簽名語法

調(diào)用簽名類似箭頭函數(shù),但使用 : 而非 =>

interface StringProcessor {
    (input: string): string;  // 調(diào)用簽名
}

const toUpper: StringProcessor = (input: string) => input.toUpperCase();
const toLower: StringProcessor = (input: string) => input.toLowerCase();

調(diào)用簽名可以包含多個(gè),用于描述函數(shù)重載。

interface OverloadedFunc {
    (x: string): string;
    (x: number): number;
}

const fn: OverloadedFunc = (x: any): any => {
    if (typeof x === "string") return x.toUpperCase();
    return x * 2;
};

1.3 調(diào)用簽名 vs 函數(shù)類型表達(dá)式

特性函數(shù)類型表達(dá)式 (a: T) => U可調(diào)用接口 { (a: T): U }
簡潔性更簡潔稍長,但可擴(kuò)展
重載不支持(單個(gè)簽名)支持多個(gè)調(diào)用簽名
額外屬性不支持可以在同一接口中添加屬性
泛型支持支持

如果只需要描述一個(gè)簡單的函數(shù)類型,函數(shù)類型表達(dá)式足夠。如果需要重載或函數(shù)對象附加屬性,用可調(diào)用接口。

二、同時(shí)具有屬性和調(diào)用能力的函數(shù)對象

JavaScript 中函數(shù)也是對象,可以添加屬性。例如 Date.now() 是靜態(tài)方法,Array.isArray 也是函數(shù)加屬性。TypeScript 允許在接口中同時(shí)定義調(diào)用簽名和屬性簽名。

interface Counter {
    (start: number): string;   // 可調(diào)用
    interval: number;          // 屬性
    reset(): void;             // 方法
}

function createCounter(): Counter {
    const counter = ((start: number) => {
        return `Count: ${start}`;
    }) as Counter;
    counter.interval = 1000;
    counter.reset = () => { console.log("reset"); };
    return counter;
}

const c = createCounter();
console.log(c(5));        // "Count: 5"
console.log(c.interval);  // 1000
c.reset();                // "reset"

這種模式在庫設(shè)計(jì)中常見,例如 jQuery 的 $ 既是函數(shù)又是對象。

2.1 實(shí)際案例:帶默認(rèn)值的加法器

interface Adder {
    (x: number): number;
    defaultValue: number;
    setDefault(value: number): void;
}

function createAdder(defaultVal: number = 0): Adder {
    const adder = (x: number) => x + adder.defaultValue;
    adder.defaultValue = defaultVal;
    adder.setDefault = (value: number) => { adder.defaultValue = value; };
    return adder;
}

const addFive = createAdder(5);
console.log(addFive(10));  // 15
addFive.setDefault(10);
console.log(addFive(10));  // 20

三、構(gòu)造簽名(Construct Signature)

3.1 語法

構(gòu)造簽名用于描述一個(gè)可以被 new 調(diào)用的構(gòu)造函數(shù)類型。語法是在調(diào)用簽名前加上 new 關(guān)鍵字。

interface PointConstructor {
    new (x: number, y: number): { x: number; y: number };
}

function createPoint(ctor: PointConstructor, x: number, y: number) {
    return new ctor(x, y);
}

class Point {
    constructor(public x: number, public y: number) {}
}

const p = createPoint(Point, 10, 20);  // { x: 10, y: 20 }

3.2 同時(shí)支持普通調(diào)用和構(gòu)造調(diào)用

一個(gè)接口可以同時(shí)包含普通調(diào)用簽名和構(gòu)造簽名,表示這個(gè)類型既可以作為普通函數(shù)調(diào)用,也可以作為構(gòu)造函數(shù)使用。例如內(nèi)置的 Date 類型:Date() 返回字符串,new Date() 返回日期對象。

interface DateConstructor {
    new (): Date;
    new (value: string | number): Date;
    (): string;
}

// 實(shí)際 Date 的類型定義類似這樣

3.3 工廠函數(shù)中的構(gòu)造簽名

構(gòu)造簽名常用于依賴注入或工廠模式,需要將類作為參數(shù)傳遞并實(shí)例化。

interface Widget {
    render(): void;
}

interface WidgetConstructor {
    new (container: HTMLElement): Widget;
}

function createWidget(ctor: WidgetConstructor, container: HTMLElement): Widget {
    return new ctor(container);
}

class Button implements Widget {
    constructor(private container: HTMLElement) {}
    render() { this.container.innerHTML = "<button>Click</button>"; }
}

const btn = createWidget(Button, document.body);
btn.render();

3.4 內(nèi)置構(gòu)造簽名示例

TypeScript 內(nèi)置類型中,ArrayPromise、Map 等都有構(gòu)造簽名。

// Array 構(gòu)造簽名簡化示意
interface ArrayConstructor {
    new <T>(...items: T[]): T[];
    <T>(...items: T[]): T[];
}

const arr1 = new Array(3);   // 使用構(gòu)造簽名
const arr2 = Array(3);       // 使用普通調(diào)用簽名(效果相同)

四、可調(diào)用接口的泛型

接口的調(diào)用簽名也可以使用泛型,使函數(shù)類型更加靈活。

interface Mapper {
    <T, U>(input: T[], fn: (item: T) => U): U[];
}

const map: Mapper = (arr, fn) => arr.map(fn);

const result = map([1, 2, 3], x => x.toString());  // result 類型為 string[]

也可以將泛型參數(shù)放在接口名后面,這樣所有調(diào)用簽名共享同組泛型參數(shù)(但通常放在調(diào)用簽名上更靈活)。

interface GenericMapper<T, U> {
    (input: T[], fn: (item: T) => U): U[];
}

const map2: GenericMapper<number, string> = (arr, fn) => arr.map(fn);
// 但這樣限制了只能用于 number -> string

五、常見錯(cuò)誤與注意事項(xiàng)

5.1 調(diào)用簽名與屬性簽名沖突

同一個(gè)接口中,不能有同名的調(diào)用簽名和屬性簽名,因?yàn)檎{(diào)用簽名本質(zhì)上是一個(gè)名為 ( ) 的特殊成員,但不會與普通屬性沖突。

5.2 實(shí)現(xiàn)可調(diào)用接口時(shí)類型不匹配

interface Fn {
    (x: number): number;
}

const fn: Fn = (x: string) => x.length;  // ? 參數(shù)類型不匹配

5.3 構(gòu)造簽名與普通函數(shù)混淆

如果接口只有構(gòu)造簽名,那么只有 new 調(diào)用才符合類型,普通調(diào)用會報(bào)錯(cuò)。

interface Ctor {
    new (x: number): number;
}

const f: Ctor = (x: number) => x;  // ? 不是構(gòu)造簽名

5.4 在對象字面量中定義可調(diào)用對象

直接在對象字面量中定義一個(gè)既有屬性又可以被調(diào)用的對象,需要使用 Object.assign 或類型斷言。

const fn = Object.assign(
    (x: number) => x * 2,
    { multiplier: 2 }
);

// 或者使用類型斷言
const fn2 = ((x: number) => x * 2) as { (x: number): number; multiplier: number };
fn2.multiplier = 2;

六、綜合示例

// 定義一個(gè)任務(wù)管理器,可調(diào)用執(zhí)行任務(wù),同時(shí)可添加任務(wù)和查看狀態(tài)
interface TaskManager {
    // 可調(diào)用:執(zhí)行所有任務(wù)
    (): void;
    // 屬性
    tasks: string[];
    count: number;
    // 方法
    add(task: string): void;
    clear(): void;
}

function createTaskManager(): TaskManager {
    const manager = (() => {
        console.log("Executing tasks:", manager.tasks);
        manager.tasks.forEach(t => console.log(`- ${t}`));
    }) as TaskManager;
    
    manager.tasks = [];
    manager.count = 0;
    manager.add = (task: string) => {
        manager.tasks.push(task);
        manager.count = manager.tasks.length;
    };
    manager.clear = () => {
        manager.tasks = [];
        manager.count = 0;
    };
    return manager;
}

const tasks = createTaskManager();
tasks.add("Write code");
tasks.add("Test");
tasks();   // 執(zhí)行任務(wù)
console.log(tasks.count);  // 2

// 構(gòu)造簽名示例:模型工廠
interface Model {
    save(): void;
}

interface ModelConstructor {
    new (data: Record<string, any>): Model;
}

function createModel(ctor: ModelConstructor, data: Record<string, any>): Model {
    return new ctor(data);
}

class User implements Model {
    constructor(public data: Record<string, any>) {}
    save() { console.log("Saving user", this.data); }
}

const user = createModel(User, { name: "Alice" });
user.save();

// 帶構(gòu)造簽名和普通調(diào)用簽名的混合接口示例(類似 Date)
interface DateTime {
    new (timestamp?: number): Date;
    (): string;
}

// 實(shí)際使用中,DateTime 類型需要匹配 Date 構(gòu)造函數(shù)的行為
const MyDate: DateTime = Date as any;
console.log(MyDate());           // 字符串
console.log(new MyDate());       // Date 對象

七、小結(jié)

概念語法示例說明
調(diào)用簽名{ (x: number): string }描述函數(shù)類型
可調(diào)用接口interface Fn { (x: number): number; }接口形式的函數(shù)類型
帶屬性的函數(shù)對象interface Cnt { (): void; count: number; }同時(shí)可調(diào)用和存儲屬性
構(gòu)造簽名{ new (x: number): Point; }描述構(gòu)造函數(shù)類型
混合簽名{ new (x: number): T; (x: number): T; }既可作為構(gòu)造函數(shù),也可作為函數(shù)調(diào)用
泛型調(diào)用簽名{ <T>(arr: T[]): T; }調(diào)用簽名中使用泛型

到此這篇關(guān)于TypeScript實(shí)現(xiàn)可調(diào)用接口與構(gòu)造簽名的文章就介紹到這了,更多相關(guān)TypeScript 可調(diào)用接口與構(gòu)造簽名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過JS判斷網(wǎng)頁是否為手機(jī)打開

    通過JS判斷網(wǎng)頁是否為手機(jī)打開

    這篇文章主要介紹了通過JS判斷網(wǎng)頁是否為手機(jī)打開,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • JavaScript與jQuery中文檔就緒函數(shù)的區(qū)別

    JavaScript與jQuery中文檔就緒函數(shù)的區(qū)別

    這篇文章主要介紹了JavaScript與jQuery中文檔就緒函數(shù)的區(qū)別,文章內(nèi)容介紹詳細(xì),具有一的的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • Openlayers學(xué)習(xí)之加載鷹眼控件

    Openlayers學(xué)習(xí)之加載鷹眼控件

    這篇文章主要介紹了Openlayers學(xué)習(xí)之加載鷹眼控件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • JavaScript數(shù)組、json對象、eval()函數(shù)用法實(shí)例分析

    JavaScript數(shù)組、json對象、eval()函數(shù)用法實(shí)例分析

    這篇文章主要介紹了JavaScript數(shù)組、json對象、eval()函數(shù)用法,結(jié)合實(shí)例形式分析了JS數(shù)組創(chuàng)建、賦值、連接、翻轉(zhuǎn),json對象定義、讀取,eval()函數(shù)的功能、使用等,需要的朋友可以參考下
    2019-02-02
  • JS中解決谷歌瀏覽器記住密碼輸入框顏色改變功能

    JS中解決谷歌瀏覽器記住密碼輸入框顏色改變功能

    這篇文章主要介紹了JS中解決谷歌瀏覽器記住密碼輸入框顏色改變功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • 最新評論

    富民县| 溆浦县| 吴旗县| 禹州市| 昌宁县| 南华县| 望谟县| 佛山市| 资阳市| 龙川县| 会昌县| 安塞县| 沂南县| 富阳市| 平湖市| 越西县| 河东区| 康乐县| 马尔康县| 日土县| 象州县| 堆龙德庆县| 昔阳县| 宜州市| 太保市| 正定县| 灵川县| 青龙| 乾安县| 吴江市| 新龙县| 兴义市| 临夏县| 石狮市| 衡山县| 新龙县| 剑川县| 仁布县| 万宁市| 东安县| 建瓯市|