代码之家  ›  专栏  ›  技术社区  ›  Nathan Friend

如何在定义为“any”的第三方TypeScript接口中扩充属性?

  •  13
  • Nathan Friend  · 技术社区  · 7 年前

    给定定义如下的第三方TypeScript模块:

    // in /node_modules/third-party-module/index.d.ts
    declare module 'ThirdPartyModule' {
        export interface ThirdPartyInterface {
            data: any;
        }
    }
    

    如何扩展此模块以更严格地键入 data 所有物

    我试过这个:

    // in /app/typings.d.ts
    declare module 'ThirdPartyModule' {
    
        interface IMyCustomType {}
    
        interface ThirdPartyInterface {
    
            // causes a compiler error: Subsequent property declarations 
            // must have the same type.  Property 'data' must be of type 
            // 'any', but here has type 'IMyCustomType'.
            data: IMyCustomType;
        }
    }
    

    但这给了我一个编译器错误:“后续的属性声明必须具有相同的类型。属性‘data’必须是‘any’类型,但此处的类型为‘IMyCustomType’。”

    如果第三方模块将属性定义为实际类型,如下所示:

    // in /node_modules/third-party-module/index.d.ts
    declare module 'ThirdPartyModule' {
        interface IAnotherThirdPartyInterface {
            something: string;
        }
    
        interface ThirdPartyInterface {
            data: IAnotherThirdPartyInterface;
        }
    }
    

    我可以简单地 IMyCustomType 接口扩展此第三方类型:

    // in /app/typings.d.ts
    declare module 'ThirdPartyModule' {
        interface IMyCustomType extends IAnotherThirdPartyInterface {}
    
        interface ThirdPartyInterface {
            data: IMyCustomType;
        }
    }
    

    但是,由于类型已定义 any ,我无法扩展它:

    // causes a compiler error:  'any' only refers to a type, 
    // but is being used as a value here.
    interface IMyCustomType extends any {}
    
    1 回复  |  直到 7 年前
        1
  •  9
  •   Titian Cernicova-Dragomir    7 年前

    虽然不能重新定义属性,但另一种方法是定义新属性,并使用此新属性扩充原始对象。虽然此解决方案通常不适用,但如果属性位于类上,则可以执行此操作。在你的情况下,你在评论中提到 hapi . 由于物业位于 Server 类,我们可以定义属性的新类型化版本。

    哈皮。加强ts

    import *  as Hapi from 'hapi'
    
    declare module 'hapi' {
        export function server(cfg: any): Hapi.Server;
        interface Server {
            typedApp:  {
                myData: string
            }
        }
    }
    
    Object.defineProperty(Hapi.Server.prototype, 'typedApp', {
        enumerable: false,
        get(this: Hapi.Server){
            return this.app;
        },
        set(this: Hapi.Server, value: any){
            this.app = value;
        }
    });
    

    用法ts

    import *  as Hapi from 'hapi'
    import './hapi.augment'
    
    const server = new Hapi.Server()
    server.connection({ port: 3000, host: 'localhost' });
    server.start();
    server.typedApp.myData = "Here";
    
    server.route({
        method: 'GET',
        path: '/',
        handler: function (request, reply) {
            reply(request.server.typedApp.myData);
        }
    });