如何在第三方TypeScript接口中扩充属性,该接口定义为;有什么;?

如何在第三方TypeScript接口中扩充属性,该接口定义为;有什么;?,typescript,module,interface,Typescript,Module,Interface,给定定义如下的第三方TypeScript模块: // in /node_modules/third-party-module/index.d.ts declare module 'ThirdPartyModule' { export interface ThirdPartyInterface { data: any; } } // in /node_modules/third-party-module/index.d.ts declare module 'Thi

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

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

    interface ThirdPartyInterface {
        data: IAnotherThirdPartyInterface;
    }
}
如何扩展此模块以更严格地键入
数据
属性?

我试过这个:

// 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' {
    export interface ThirdPartyInterface {
        data: any;
    }
}
// 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 {}

虽然不能重新定义属性,但另一种方法是定义新属性,并使用此新属性扩充原始对象。虽然此解决方案通常不适用,但如果属性位于类上,则可以执行此操作。在您的案例中,您在注释
hapi
中提到。由于属性位于
服务器
类上,我们可以定义属性的新类型版本

hapi.augment.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;
    }
});
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);
    }
});
用法。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;
    }
});
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);
    }
});

您的用例是什么?是否要在库中为调用设置更严格的类型?或者,对于需要类似数据结构的函数,您是否需要此接口?我正在尝试重写的类型。属性是存储应用程序数据的通用位置,因此库的作者将其键入为
any
。但是,由于我知道如何使用这个属性,我想向这个属性添加键入信息以避免强制转换。嗯,我必须承认,对于这个问题,我从来没有找到比“使用库的本地修改版本”更好的答案(如果对每个人都好的话,可能会尝试将这样的版本推到上游)。声明合并在某些方面不够精细,这是难点之一。我也有兴趣看到一个更好的答案。@jcalz您可能无法重新定义它,但您可以有一个类型化的替代方案。在这种情况下,它可能同样有用。非常有趣的解决方案!这让我更接近我想要的。谢谢你的例子!