我試圖用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