title: Angular: Can i have a private service scoped to its module?
body: <p>In an angular 5 application, I have a module responsible for dispensing a specific piece of data. This service injects two services -- one retrieves data from <code>localStorage</code>, if found, and another that requests the same data from the server if not found. I want this module to expose the retrieved data without exposing the services that actually do the retrieval, but i am having problems.</p>
  
  <p><strong>DataService:</strong> </p>
  
  <pre class="lang-js prettyprint-override"><code>@Injectable()
  export class DataService {
    constructor(private httpService: HttpService,
                private storageService: LocalStorageService) { }
  
    get = (): Observable&lt;User&gt; =&gt; {
      const data: string = this.storageService.fetch();
      if (data) {
        return Observable.of(JSON.parse(data));
      }
      return this.httpService
        .get();
    };
  }
  </code></pre>
  
  <p><strong>HttpService:</strong> </p>
  
  <pre class="lang-js prettyprint-override"><code>@Injectable()
  export class HttpService {
  
    private dataUrl = 'api/endpoint';
    constructor(private http: HttpClient,
                private storageService: LocalStorageService) {}
    get = () =&gt; {
      return this.http
        .get(this.dataUrl)
        .map((retrieved: any) =&gt; {
          this.storageService.store(retrieved);
          return retrieved;
        }).catch(() =&gt; Observable.throw(err));
    };
  }
  </code></pre>
  
  <p><strong>LocalStorageService:</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>@Injectable()
  export class LocalStorageService {
  
    private key = 'dataKey';
  
    constructor() { }
  
    fetch = (): string =&gt; {
      return localStorage.getItem(this.key); 
    };
  
    store(d: any): void  {
      localStorage.setItem(this.key, JSON.stringify(d));
    };
  }
  </code></pre>
  
  <p>I tried defining the module by exposing only <code>DataService</code>:</p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    imports: [
      CommonModule
    ],
    providers: [
      DataService
    ]
  })
  export class DataModule {}
  </code></pre>
  
  <p>The result was <code>StaticInjectorError[HttpService]: NullInjectorError: No provider for HttpService!"</code> and a similar error for <code>LocalStorageService</code>, both thrown by <code>app.module</code>.</p>
  
  <p>I can get the app working by redefining the <code>NgModule</code> providers declaration to include the injected services that should remain private: </p>
  
  <pre class="lang-js prettyprint-override"><code>@NgModule({
    imports: [
      CommonModule
    ],
    providers: [
      DataService,
      LocalStorageService,
      HttpService
    ]
  })
  export class DataModule {}
  </code></pre>
  
  <p>However, this exposes those services to any module importing <code>DataModule</code>, which is specifically what i want to avoid. Is there a way to make an <code>@Injectable</code> available for dependency injection within a module without adding it to <code>providers</code> and exposing it outside the module?</p>