Я пытаюсь чисто написать Угловое расширение пользовательских $resource
как завод как класс машинопись с использованием DefinatelyTyped (IResource
, IResourceClass
и друзей).
По 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);
}
Трюк должен был;
- Поднять методы, которые я хочу на обслуживание, в базовый класс, потому что этот метод не инициализируется к тому моменту, когда вызывается моя функция constructor().
svc
, который является угловым сервисом от конструктора, который вы можете сделать в JavaScript, конечно, но это похоже на действительно грязную утиную печать в TypeScript.- Чтобы получить методы в svc.prototype, я распространяю это непосредственно из моего базового класса. Это особенно неприятно, так как это означает создание прототипа каждый раз, когда создается экземпляр.
- Последним острым ароматом этого сэндвича sh ** я должен вызвать super() для конструктора для экземпляра, который я выбрасываю, чтобы заставить его скомпилировать.
Однако, в конце всего этого, я могу добавить методы к NamedEntityResourceBase
, и они появятся в прототипе всех объектов, загруженных из моего HTTP-ресурса.
Спасибо, но я не понимаю, как это помогает мне расширить ресурс $. У вас есть пример? – cirrus