我试图用DefinatelyTyped(IResource
,IResourceClass
和朋友)干净地编写一个角度自定义$resource
扩展作为TypeScript类的工厂。
根据Misko Hevery资源只是constructor
功能,所以我期待能够定义我$resource
与一些类型安全接口(INamedEntityResource
或INamedEntity
),并混入服务定义一个普通类,但我似乎无法得到我的NamedEntityResource原型上的标准类方法最终在工厂实例上结束。
有没有办法做到这一点与constructor()
功能,或者我应该放弃,只是在普通的JavaScript定义服务?
declare module EntityTypes {
interface INamedEntity { }
}
module Services {
export interface INamedEntitySvc {
Name(params: {}, successCallback: (data: any, headers: any) => void, errorCallback: (data: any, headers: any) => void): EntityTypes.INamedEntity;
Clear(params: {}, value: EntityTypes.INamedEntity, successCallback: (data: any, headers: any) => void, errorCallback: (data: any, headers: any) => void): EntityTypes.INamedEntity;
}
// WILL have correct interface definition for the resource
export interface INamedEntityResource extends NamedEntityResource, INamedEntitySvc { }
export class NamedEntityResource {
// #1 DOESN'T WORK - These are on NamedEntityResource.prototype but don't end up on svc
public someMethod() { }
public someOtherMethod() { }
constructor($resource) {
var paramDefaults = {
};
var svc: INamedEntitySvc = $resource(getUrl(), paramDefaults, {
Name: <any>{ method: "GET", params: { action: "Name" } },
Clear: <any>{ method: "PATCH", params: { action: "Clear" }, headers: { 'Content-Type': 'application/json' } },
});
// THIS WORKS - but it's not a NamedEntityResource
svc["prototype"].someMethod = function() { }
svc["prototype"].someOtherMethod = function() { }
return <any>svc;
// #1 DOESN'T WORK THOUGH
return; // doesn't pick up methods on prototype
// #2 THIS DOESN'T WORK EITHER
NamedEntityResource["prototype"] = angular.extend(this["prototype"] || {}, svc["prototype"]);
return this;
}
}
// Registration
var servicesModule: ng.IModule = angular.module('npApp.services');
servicesModule.factory('NamedEntityResource', NamedEntityResource);
}
进一步
所以这样做的目的是为了让我写一个资源类{}与将在每个资源我加载通过HTTP进行注释的方法。在这种情况下,我的INamedEntity
s。
这是我迄今为止能够得到的最接近的解决方案,看起来可行,但感觉真的很讨厌。
module Services {
export interface INamedEntitySvc {
Name(params: {}, successCallback: (data: any, headers: any) => void, errorCallback: (data: any, headers: any) => void): EntityTypes.INamedEntity;
Clear(params: {}, value: EntityTypes.INamedEntity, successCallback: (data: any, headers: any) => void, errorCallback: (data: any, headers: any) => void): EntityTypes.INamedEntity;
}
// WILL have correct interface definition for the resource
export interface INamedEntityResource extends NamedEntityResource, INamedEntitySvc { }
export class NamedEntityResourceBase {
public someMethod() { }
public someOtherMethod() { }
}
// extend our resource implementation so that INamedEntityResource will have all the relevant intelisense
export class NamedEntityResource extends NamedEntityResourceBase {
constructor($resource) {
super(); // kind of superfluous since we're not actually using this instance but the compiler requires it
var svc: INamedEntitySvc = $resource(getUrl(), { }, {
Name: <any>{ method: "GET", params: { action: "Name" } },
Clear: <any>{ method: "PATCH", params: { action: "Clear" }, headers: { 'Content-Type': 'application/json' } },
});
// Mixin svc definition to ourself - we have to use a hoisted base class because this.prototype isn't setup yet
angular.extend(svc["prototype"], NamedEntityResourceBase["prototype"]);
// Return Angular's service (NOT this instance) mixed in with the methods we want from the base class
return <any>svc;
}
thisWontWork() {
// since we never actually get a NamedEntityResource instance, this method cannot be applied to anything.
// any methods you want have to go in the base prototype
}
}
// Registration
var servicesModule: ng.IModule = angular.module('npApp.services');
servicesModule.factory('NamedEntityResource', NamedEntityResource);
}
诀窍是:
- 将我想要的服务上的方法提升到基类中,因为this.prototype没有在构造函数调用的时候被初始化。
- 返回
svc
这是来自构造函数的角度$resource
服务,您当然可以在JavaScript中执行该服务,但它在TypeScript中感觉非常脏鸭式输入。 - 为了得到svc.prototype上的方法,我直接从我的基类扩展。这特别令人讨厌,因为它意味着每次创建实例时都要设置原型。
- 这个sh **三明治的最后的辛辣气味是我必须在构造函数上调用super(),以便让它进行编译。
但是,最后,我可以将方法添加到NamedEntityResourceBase
,它们将出现在从我的HTTP资源加载的所有实体的原型中。
谢谢,但我不清楚这是如何帮助我扩展$资源。你有一个例子吗? – cirrus