Inheritance or Injecting in Typescript - node.js

I create an large project with using Typescript and NestJS framework, I want to create this project in OOP architecture and I have a want important question about it. I want to create one, base service with commons function that will be use in almost every service in the project, and I have a two ways to using a common parts.
First is to create an abstract class with commons methods like below:
export abstract class BaseService {}
and inheritance this abstract class in the target service:
export class UserService extends BaseService {}
Thanks of this I can use all of the methods that exists in BaseService with using this keyword and creating an reference to the function.
But I have a second approach, with using Injecting service via constrcutor:
export class BaseService {}
and injecting via constructor:
export class UserService {
constructor (
private readonly baseService: BaseService
){}
someMethod(): void {
return baseService.getHelloWorld();
}
}
In this way I can to create an reference stricte from injecting service.
And now i have a question. Which approach is better in the large project?
PS. I prefer to create an generic function based on <T> on methods instead of class

In this particular case delegation to an injected service is more appropriate. If you do this, you should probably rename BaseService to something that does not imply that it is a base class to be inherited by other service classes. I suggest SharedService or CommonService.
Delegation is better here because your design suggests that the BaseService and UserService do not have the same meaning and purpose but only have common operations. Reducing code duplication should not be the main justification for choosing inheritance.

Related

NestJs instantiate class with dependencies

I'm completely new to Nestjs moving from Laravel, really enjoying it, but it's kinda more difficult to find answers online.
I got a base class with a dependency of the HttpService:
export abstract class BaseClass {
constructor(protected httpService: HttpService) {}
}
I got a couple of classes extending the base class, and I'm trying to instantiate them on the fly:
const bus = new BusClass([
new classNumber1(this.httpService),
new classNumber2(this.httpService),
]);
I want to find a way to NOT pass the httpService to the constructors,
just like NestJs doing it when we inject services on the constructors in the controllers for example.
I tried with factories and really any example from the docs, with no success.
Will be glad for any kind of help, thanks allot ahead!

When to use ExceptionFilter vs BaseExceptionFilter in NestJS?

What is the diff b/w both types of filters. And when to use what? Please explain with any example
#Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
}
#Catch()
export class AllExceptionsFilter extends BaseExceptionFilter {
}
ExceptionFilter is an interface that defines that the current class should implement the catch method with the signature (exception: unknown, host: ArgumentHost).
BaseExceptionFilter is a class already made in NestJS with a working catch method. By using extend you can add your own logic to catch and then in the end of the implementation call super.catch(exception, host) and let Nest take care of the rest from there.
The main difference of the two is how much of the logic do you want to write vs how much do you want to add in. If you are happy with how Nest already handles errors, and just want to add in the ability to log your errors, say to a database, then extends BaseExceptionFilter is a good fit. However, if you don't care or how Nest's exception filter works by default, then implements ExceptionFilter and writing your own custom logic is the way to go.

NestJS (node) - Validate request by generic type

I have two NestJS controllers
export class ParentController<T> {
constructor(protected service: Service<T>) {}
#Post()
do(#Body() dto: ClassType<T>): Promise<T> {
return this.service.do(dto);
}
}
... and another controller, extends parent
#Controller('any')
export class AnyController extends ParentController<Entity> {
constructor(protected service: Service) {
super(service);
}
}
As you see TypeORM Entity bound with this controller as T via generics. In "do(...)" method i used ClassType as type for validation, but validation doesn't triggered at all without having any errors. As i understand it needs exactly class, not type to be defined as DTO.
My question is: How can i apply validation on method "do(...)" using just my Entity type (not using Entity itself in ParentController). I know generics don't exist at the JS runtime, and it's hard to make abstract controller without having this feature.
P.S. I need to do it without using nestjsx/crud component
You can't do that in that way.
Actually, that was one of the reasons why I created nestjsx/crud package that uses #Crud() decorator where you pass entity type for validation.
Another option - you can create a mixin and pass an entity there.

typescript dependency injection with little footprint

I am new to nodejs and typescript, coming from C#.
I want to use dependency injection in my project and found that the most popular package is inversify.
I started using it but I don't like the fact that I have to add decorators all over.
for example it bothers me that I need to add #inject before parameters in the constructor:
public constructor(
#inject(TYPES.Weapon) katana: Weapon,
#inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon
)
This mean every class has to know the TYPES object...
I don't understand why #inject needs the string literal and can't inject just on the basis of the type...
Is there a neater way to do this?
In contrast to strictly typed languages, TypeScript types don't exist at runtime. It's possible to use type information at runtime for dependency injection but in limited ways. With the use of emitDecoratorMetadata TypeScript option it's possible to get constructor parameter types and use them for DI.
The example is injection-js, which is Angular injector that was extracted from the library for standalone use. Only #Injectable decorator is needed to be used on DI-enabled class, #Inject parameter decorators are optional.
The limitations are that only class instances can be injected this way:
constructor(foo: FooClass) {}
Generics are ignored and discarded:
constructor(foo: FooClass<Bar>) {}
Other types are ignored and result in DI error:
constructor(foo: fooSymbol) {}
constructor(foo: 'foo string provider') {}
The same applies to InversifyJS:
In case of concrete injections, you can simply define your constructor
parameters as usual without using the #inject decorator.
InversifyJS also supports TypeScript's constructor assignments so you
can have private or protected access modifiers in your parameters and
the container will have no trouble injecting the dependencies
It would be possible to omit #inject for Weapon and ThrowableWeapon if they were classes but in listed example TYPES.Weapon is a symbol and Weapon is an interface that doesn't exist at runtime, so #inject is necessary.

How do I make a public view model base with WinRT classes?

I wanted to create an abstract base class for all of my view models, but I'm running into accessibility issues and can't seem to navigate through the errors. Here's an example of my code:
public ref class ViewModelBase {
...
}
public ref class OtherViewModel : ViewModelBase {
...
}
When I define my code as state above, I get the following error:
error C4585: 'MyNamespace::ViewModelBase' : A WinRT 'public ref class' must either be sealed or derive from an existing unsealed class
If, instead, I make ViewModelBase private, I get this error:
error C3213: base class 'MyNamespace::ViewModelBase' is less accessible than 'OtherViewModel'
This seems like it should be incredibly simple. What am I doing wrong?
What you are attempting is not strictly possible in C++/CX, as in VS 2012 C++/CX does not support public class inheritance for general-purpose scenarios. It is only supported enough to have the XAML scenarios work; the only possible public unsealed types are those found under the Windows::UI::Xaml namespace, and users are not able to author their own public unsealed types.
If you want to have a base class for all your view models, your only options to make all your classes private or to inherit from a base class from Windows::UI::Xaml (such as DependencyObject).
Each of these approaches has drawbacks:
using DependencyObject as your base makes all your viewmodels STA objects (so they can only be manipulated from the UI thread) in addition to having a lot of overhead that isn't really necessary.
Making your classes private means you cannot use the [Bindable] attribute to do databinding, so you would need to have a private databinding implementation. (Your private class would need to implement ICustomPropertyProvider and related interfaces.)
The "sealed" keyword means that the class cannot be inherited from. Your implementation should look something like this:
ref class ViewModelBase sealed
If you want to inherit from ViewModelBase then you need to have only the subclasses be ref classes like this:
class ViewModelBase
...
public ref class OtherViewModel sealed : ViewModelBase

Resources