5

I am currently learning the Angular framework (version 5) after developing 2 years with the AngularJS 1.x framework, so I ask myself a lot of questions and one of them is the way to properly import a service provided by another module that the one of my application.

Let's say that I have a CoreModule for example which provide a MyService service, and let's say that the project has the following file tree:

app/
   app.module.ts
   ...
pages/
   clients/
      clients.component.html
      clients.component.css
      clients.component.ts
   ...
core/
   core.module.ts
   providers/
      my-service.service.ts

Now let's say that my clients page needs to inject the MyService service from the CoreModule module. To do that I will put MyService in the providers list of the CoreModule module. And I will import the CoreModule in my AppModule.

If I well understood, by doing such an import, I will say to my application to use the MyService service when it is required in the .ts files of the AppModule module.

But the thing I cannot understand is the inclusion of the .ts file declaring the service in my application code. Indeed, if I want to use the MyService service, I will do something like that in my Clients class:

constructor(private service: MyService) {
   // using of the injected service
}

But TypeScript needs the reference of the .ts file which declared the service. My first try would be to import the file by following the file tree:

import { MyService } from '../../core/providers/my-service.service';

But it does not feel right to me because when I import an Angular service I do not have to specify the path to access to the file which declare the service in question. Example with the HttpClient service:

import { HttpClient } from '@angular/common/http';

Actually, I would like to be able to import my core service in my application page by referencing the module and not by passing the path of the .ts file.

At that point, I don't know if it is even possible or if I misunderstood the use of service from other modules.

Alexandre D.
  • 711
  • 1
  • 9
  • 28

2 Answers2

1

When you doing this

constructor(private service: MyService) {
   // using of the injected service
}

You are injecting dependency into this class. That means, that Angular will create an instance of MyService class and pass it into constructor of your component at creation time.

When you doing this

import { MyService } from '../../core/providers/my-service.service';

That just says TypeScript that such class exist, which class you are referring to, and also allows TypeScript to perform type checks correctly. It is nothing more than just pointer to exact MyService class location, because you might have multiple classes with such name in a different files.

I wouldn't say that HttpClient is a service, just an ordinary class helper.

So, all the work still done in the constructor declaration level. This is for Angular and dependency injection. Additional import is for TypeScript mostly.

Artsiom Miksiuk
  • 3,896
  • 9
  • 33
  • 49
  • First of all, thanks for your reply. Are you saying that importing a service from another module by referencing it through it path in TypeScript is the right way to do? Because let's say I want to reuse this module in another application to be able to access to `MyService`, I would have to adapt the path to my new project. Is there a way to import the service by doing something like `import { MyService } from 'SharedModule';` ? – Alexandre D. Nov 28 '17 at 08:15
  • 1
    Then it is nothing to do with TypeScript or Angular at all. Import statements is a basic JavaScript in context of node.js (in browsers as well if you are using bundling) statements. You need to investigate how modules requiring working in node.js to answer this question. Short answer, yes, you can do what you've written. It can be done in a several ways. – Artsiom Miksiuk Nov 28 '17 at 09:03
0

Assuming you want to import your service with the following statement:

    import { MyService } from "/path/myModule"; 

Typescript tries to locate a definition (service, component etc) in the following sequence:

  1. it tries to find an export to MyService in myModule file (i.e. /path/myModule.ts, /path/myModule.tsx or /path/myModule.d.ts);
  2. it searches for a types property in the /path/myModule/package.json file, if it exists;
  3. it seeks for an index file in myModule folder (i.e. /path/myModule/index.ts, /path/myModule/index.tsx or /path/myModule/index.d.ts).

So, to accomplish your goal, you can define an index.ts file as a barrel to export your service. That's exactly the strategy used to export the HttpClient service. The commons/http source folder contains an index.ts file with the following code:

export * from './public_api';

And the public_api.ts file contains the following line:

export {HttpClient} from './src/client';

You can find more details about typescript module resolution in the Module Resolution section of The TypeScript Handbook.

Jideão Filho
  • 85
  • 1
  • 7