<p dir="auto"><strong>I'm submitting a ...</strong>  (check one with "x")</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[ ] bug report
[x] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question"><pre class="notranslate"><code class="notranslate">[ ] bug report
[x] feature request
[ ] support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
</code></pre></div>
<p dir="auto">With the current injectior options you can't redefine a service that uses his parent, because of a circular dependency.</p>
<p dir="auto">For instance, imagine I make a new service, called <code class="notranslate">HttpA</code> that uses the <code class="notranslate">Http</code> service but adding a functionality. Now, as long as my service extends <code class="notranslate">Http</code> or explicitly uses <code class="notranslate">Http</code> (by creating an instance) I can declare a provider for this service with:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="provide(HttpA, {
    useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =&gt; {
        return new HttpA(xhrBackend, requestOptions);
    },
    deps: [XHRBackend, RequestOptions]
})"><pre class="notranslate"><span class="pl-en">provide</span><span class="pl-kos">(</span><span class="pl-v">HttpA</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">useFactory</span>: <span class="pl-kos">(</span><span class="pl-s1">xhrBackend</span>: <span class="pl-v">XHRBackend</span><span class="pl-kos">,</span> <span class="pl-c1">requestOptions</span>: <span class="pl-v">RequestOptions</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c1">return</span> <span class="pl-s1">new</span> <span class="pl-v">HttpA</span><span class="pl-kos">(</span><span class="pl-s1">xhrBackend</span><span class="pl-kos">,</span> <span class="pl-s1">requestOptions</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-v">XHRBackend</span><span class="pl-kos">,</span> <span class="pl-v">RequestOptions</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">But now, maybe I don't want to go through all my application and change all the Http references to HttpA, so I can do something like this:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="provide(Http, {
    useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =&gt; {
        return new HttpA(xhrBackend, requestOptions);
    },
    deps: [XHRBackend, RequestOptions]
})"><pre class="notranslate"><span class="pl-en">provide</span><span class="pl-kos">(</span><span class="pl-v">Http</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-c1">useFactory</span>: <span class="pl-kos">(</span><span class="pl-s1">xhrBackend</span>: <span class="pl-v">XHRBackend</span><span class="pl-kos">,</span> <span class="pl-c1">requestOptions</span>: <span class="pl-v">RequestOptions</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c1">return</span> <span class="pl-s1">new</span> <span class="pl-v">HttpA</span><span class="pl-kos">(</span><span class="pl-s1">xhrBackend</span><span class="pl-kos">,</span> <span class="pl-s1">requestOptions</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-v">XHRBackend</span><span class="pl-kos">,</span> <span class="pl-v">RequestOptions</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">And this will work perfectly.</p>
<p dir="auto">But what will happen if we create another Http-based service called <code class="notranslate">HttpB</code> that adds a different functionality from <code class="notranslate">HttpA</code>? If we use the same provider as <code class="notranslate">HttpA</code> it will replace that implementation with the new one, because we will be telling the injector that whenever someone asks for the <code class="notranslate">Http</code> service, give him the <code class="notranslate">HttpB</code> service instance that we just created, that it uses or extends @angular/core <code class="notranslate">Http</code>, thus the functionality in <code class="notranslate">HttpA</code> will be lost.</p>
<p dir="auto">The problem then is that when we try to use the injector to get the last <code class="notranslate">Http</code> implementation we get a cyclic dependency error:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="provide(Http, {
    useFactory: (http:Http) =&gt; {
        return new HttpA(http);
    },
    deps: [Http]
})"><pre class="notranslate"><span class="pl-en">provide</span><span class="pl-kos">(</span><span class="pl-v">Http</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-en">useFactory</span>: <span class="pl-kos">(</span><span class="pl-s1">http</span>:<span class="pl-v">Http</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">HttpA</span><span class="pl-kos">(</span><span class="pl-s1">http</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-v">Http</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">And it makes sense if you read it like "When someone asks the <code class="notranslate">Http</code> service, get the <code class="notranslate">Http</code> service and use <code class="notranslate">HttpA</code> instead", but wouldn't it be cool the injector to know that the <code class="notranslate">Http</code> service we are injecting in the provider is not the same we are returning? (i.e., it's the last defined implementation)? In fact, the behaviour that I want would be like:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="provide(Http, {
    useFactory: (http:OldHttp) =&gt; {
        return new HttpA(http);
    },
    deps: [OldHttp]
})"><pre class="notranslate"><span class="pl-en">provide</span><span class="pl-kos">(</span><span class="pl-v">Http</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
    <span class="pl-en">useFactory</span>: <span class="pl-kos">(</span><span class="pl-s1">http</span>:<span class="pl-v">OldHttp</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-v">HttpA</span><span class="pl-kos">(</span><span class="pl-s1">http</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-v">OldHttp</span><span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">But of course this won't work now because OldHttp is not defined (this is just the behaviour I mean)</p>
<p dir="auto">This would let the developers do these kind of chaining, with any service (Angular 2 or custom)</p>
<p dir="auto"><em>PS: This feature was crafted from a talk in AngularCamp Barcelona June 2016</em></p>
<h2 dir="auto">I'm submitting a...</h2>

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="
[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[ ] Documentation issue or request
[ ] Support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question"><pre class="notranslate"><code class="notranslate">
[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[x] Feature request
[ ] Documentation issue or request
[ ] Support request =&gt; Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
</code></pre></div>
<p dir="auto">Supersedes <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="209202050" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/14620" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/14620/hovercard" href="https://github.com/angular/angular/issues/14620">#14620</a> with more concrete summary and design.</p>
<h2 dir="auto">Current behavior</h2>

<p dir="auto">It's currently not possible to wrap an existing provider in the same injector, which causing:</p>
<h4 dir="auto">Class inheritance problems</h4>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="257380561" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/19181" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/19181/hovercard" href="https://github.com/angular/angular/issues/19181">#19181</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="290464434" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/21697" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/21697/hovercard" href="https://github.com/angular/angular/issues/21697">#21697</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="294147849" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/22011" data-hovercard-type="pull_request" data-hovercard-url="/angular/angular/pull/22011/hovercard?comment_id=166260795&amp;comment_type=review_comment" href="https://github.com/angular/angular/pull/22011#discussion_r166260795">#22011 (comment)</a>, ... (<code class="notranslate">class extends ErrorHandler</code>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="254349686" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/18976" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/18976/hovercard" href="https://github.com/angular/angular/issues/18976">#18976</a> (<code class="notranslate">class extends Location</code>)</li>
</ul>
<p dir="auto"><em>In Angular, the constructor is not consider public API due to the DI system, so extending class would be problematic and may require lots of boilerplate (declare deps again).</em></p>
<h4 dir="auto">Customize existing service problems</h4>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="294444229" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/22024" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/22024/hovercard" href="https://github.com/angular/angular/issues/22024">#22024</a> (<code class="notranslate">RendererFactory2</code>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="222996234" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/16184" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/16184/hovercard" href="https://github.com/angular/angular/issues/16184">#16184</a> (<code class="notranslate">DefaultRouteReuseStrategy</code>)</li>
</ul>
<p dir="auto"><em>The declared class may not be same to the provided one, the latter may not be exposed to user.</em></p>
<h4 dir="auto">Strategy pattern design problems</h4>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="104186925" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/3929" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/3929/hovercard" href="https://github.com/angular/angular/issues/3929">#3929</a> (<code class="notranslate">Renderer</code>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="174905639" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/11309" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/11309/hovercard" href="https://github.com/angular/angular/issues/11309">#11309</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="248252275" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/18554" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/18554/hovercard" href="https://github.com/angular/angular/issues/18554">#18554</a> (<code class="notranslate">IterableDiffers</code>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="243251648" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/18155" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/18155/hovercard" href="https://github.com/angular/angular/issues/18155">#18155</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="267447326" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/19852" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/19852/hovercard" href="https://github.com/angular/angular/issues/19852">#19852</a> (<code class="notranslate">HttpInterceptor</code>)</li>
</ul>
<p dir="auto"><em>Extends behavior of some poor-designed services.</em></p>
<h2 dir="auto">Expected behavior</h2>

<h4 dir="auto">API Design</h4>
<p dir="auto">The term <code class="notranslate">decorator</code> is not fit to this any more (due to other meanings), currently choose <code class="notranslate">intercept</code> for similar usage to <code class="notranslate">HttpInterceptor</code>. (still open to bikeshed)</p>
<p dir="auto">An optional <code class="notranslate">intercept</code> property like <code class="notranslate">multi</code> applies to all kinds of providers:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Injectable()
class CustomErrorHandler implements ErrorHandler {
  constructor(private handler: ErrorHandler) {}

  handleError(error: any) {
    // custom error collecting or reporting
    this.handler.handleError(error)
  }
}

@NgModule({
  providers: [
    { provide: ErrorHandler, useClass: CustomErrorHandler, intercept: true }
  ]
})
class AppModule { }"><pre class="notranslate">@<span class="pl-smi">Injectable</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">CustomErrorHandler</span> <span class="pl-k">implements</span> <span class="pl-smi">ErrorHandler</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">private</span> <span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

  <span class="pl-en">handleError</span><span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// custom error collecting or reporting</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">handler</span><span class="pl-kos">.</span><span class="pl-en">handleError</span><span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span></pre></div>
<h4 dir="auto">Semantics</h4>
<p dir="auto">Ref: <a href="https://docs.angularjs.org/guide/decorators" rel="nofollow">AngularJS Decorator API</a>.</p>
<p dir="auto">By setting <code class="notranslate">intercept: true</code>, it would allowed to inject (previous instance of) the token it providers, so it helps reusing existing logic (no need to rewrite) without modifying the consumer part (in same token).</p>
<p dir="auto">So only combining with <code class="notranslate">useClass</code> or <code class="notranslate">useFactory</code> makes sense.</p>
<p dir="auto"><code class="notranslate">{ provide: TOKEN, useExisting: TOKEN, intercept: true }</code> would not be allowed.<br>
<code class="notranslate">{ provide: TOKEN, useValue: VALUE, intercept: true }</code> is technically valid but meaningless, could cause either warning or error.</p>
<p dir="auto">Edge case: for <code class="notranslate">multi: true</code> provider, interceptor should transform the instances array, namely getting the existing array and returning a new array.</p>
<p dir="auto"><code class="notranslate">{ provide: TOKEN, useClass: CLASS, multi: true, intercept: true }</code> would not be allowed, as it cannot return an array.</p>
<p dir="auto">Inconsistent <code class="notranslate">multi</code> value between concrete provider and interceptor in same injector would not be allowed.</p>
<h4 dir="auto">Scoping</h4>
<p dir="auto">Any interceptor would belong to a specific <code class="notranslate">Injector</code> thus supporting inheritance. For example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({
  providers: [
    { provide: ErrorHandler, useFactory: func2, deps: [ErrorHandler], intercept: true },
  ]
})
class MyComponent {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func2(func1(/*original*/ErrorHandler))
  }
}

@NgModule({
  providers: [
    { provide: ErrorHandler, useFactory: func1, deps: [ErrorHandler], intercept: true },
  ]
})
class MyModule {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func1(/*original*/ErrorHandler)
  }
}"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func2</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func2(func1(/*original*/ErrorHandler))</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func1</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyModule</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func1(/*original*/ErrorHandler)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Providing the normal instance won't be affected by interceptor in parent <code class="notranslate">Injector</code>. For example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({
  providers: [
    { provide: ErrorHandler, useClass: CustomErrorHandler },
  ]
})
class MyComponent {
  constructor(handler: ErrorHandler) {
    // handler -&gt; CustomErrorHandler
  }
}

@NgModule({
  providers: [
    { provide: ErrorHandler, useFactory: func1, deps: [ErrorHandler], intercept: true },
  ]
})
class MyModule {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func1(/*original*/ErrorHandler)
  }
}"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; CustomErrorHandler</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func1</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyModule</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func1(/*original*/ErrorHandler)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Should intercepting <code class="notranslate">multi: true</code> providers at each level. For example:</p>
<p dir="auto">(Without <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="253156434" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/18894" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/18894/hovercard" href="https://github.com/angular/angular/issues/18894">#18894</a>)</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({
  providers: [
    { provide: ERROR_HANDLERS, useValue: errorHandler3, multi: true },
    { provide: ERROR_HANDLERS, useValue: errorHandler4, multi: true },
    { provide: ERROR_HANDLERS, useFactory: func2, deps: [ErrorHandler], multi: true, intercept: true },
  ]
})
class MyComponent {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func2([errorHandler3, errorHandler4])
  }
}

@NgModule({
  providers: [
    { provide: ERROR_HANDLERS, useValue: errorHandler1, multi: true },
    { provide: ERROR_HANDLERS, useValue: errorHandler2, multi: true },
    { provide: ERROR_HANDLERS, useFactory: func1, deps: [ErrorHandler], multi: true, intercept: true },
  ]
})
class MyModule {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func1([errorHandler1, errorHandler2])
  }
}"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler3</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler4</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func2</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func2([errorHandler3, errorHandler4])</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler1</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler2</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func1</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyModule</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func1([errorHandler1, errorHandler2])</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">(With <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="253156434" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/18894" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/18894/hovercard" href="https://github.com/angular/angular/issues/18894">#18894</a>)</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({
  providers: [
    { provide: ERROR_HANDLERS, useValue: errorHandler3, multi: true },
    { provide: ERROR_HANDLERS, useValue: errorHandler4, multi: true },
    { provide: ERROR_HANDLERS, useFactory: func2, deps: [ErrorHandler], multi: true, intercept: true },
  ]
})
class MyComponent {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func2([...func1([errorHandler1, errorHandler2]), errorHandler3, errorHandler4])
  }
}

@NgModule({
  providers: [
    { provide: ERROR_HANDLERS, useValue: errorHandler1, multi: true },
    { provide: ERROR_HANDLERS, useValue: errorHandler2, multi: true },
    { provide: ERROR_HANDLERS, useFactory: func1, deps: [ErrorHandler], multi: true, intercept: true },
  ]
})
class MyModule {
  constructor(handler: ErrorHandler) {
    // handler -&gt; func1([errorHandler1, errorHandler2])
  }
}"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler3</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler4</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func2</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func2([...func1([errorHandler1, errorHandler2]), errorHandler3, errorHandler4])</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler1</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useValue</span>: <span class="pl-s1">errorHandler2</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ERROR_HANDLERS</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">func1</span><span class="pl-kos">,</span> <span class="pl-c1">deps</span>: <span class="pl-kos">[</span><span class="pl-smi">ErrorHandler</span><span class="pl-kos">]</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyModule</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; func1([errorHandler1, errorHandler2])</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<h4 dir="auto">Ordering</h4>
<p dir="auto">All interceptors are considered <code class="notranslate">multi</code> provider and applied last (local to <code class="notranslate">Injector</code>). For example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@NgModule({
  providers: [
    { provide: ErrorHandler, useClass: CustomErrorHandler1 },
    { provide: ErrorHandler, useClass: CustomErrorHandler2, intercept: true },
    { provide: ErrorHandler, useClass: CustomErrorHandler3 },
    { provide: ErrorHandler, useClass: CustomErrorHandler4, intercept: true },
  ]
})
class AppModule {
  constructor(handler: ErrorHandler) {
    // handler -&gt; new CustomErrorHandler4(new CustomErrorHandler2(new CustomErrorHandler3(/* ... */)))
  }
}"><pre class="notranslate">@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler1</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler2</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler3</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler4</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// handler -&gt; new CustomErrorHandler4(new CustomErrorHandler2(new CustomErrorHandler3(/* ... */)))</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<h4 dir="auto">Examples</h4>
<p dir="auto">Reduce class inheritance:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Injectable()
class CustomErrorHandler implements ErrorHandler {
  constructor(private handler: ErrorHandler) {}

  handleError(error: any) {
    // custom error collecting or reporting
    this.handler.handleError(error)
  }
}

@NgModule({
  providers: [
    { provide: ErrorHandler, useClass: CustomErrorHandler, intercept: true }
  ]
})
class AppModule { }"><pre class="notranslate">@<span class="pl-smi">Injectable</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">CustomErrorHandler</span> <span class="pl-k">implements</span> <span class="pl-smi">ErrorHandler</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">private</span> <span class="pl-s1">handler</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

  <span class="pl-en">handleError</span><span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c">// custom error collecting or reporting</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">handler</span><span class="pl-kos">.</span><span class="pl-en">handleError</span><span class="pl-kos">(</span><span class="pl-s1">error</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">ErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomErrorHandler</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span></pre></div>
<p dir="auto">Protect private APIs:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@NgModule({
  providers: [
    { provide: RendererFactory2, useClass: CustomRendererFactory2, intercept: true }
  ]
})
class AppModule { }"><pre class="notranslate">@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">RendererFactory2</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomRendererFactory2</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span></pre></div>
<p dir="auto">Applying new strategy:</p>
<p dir="auto"><sub>Actually this is not the best way to solve that problem, exposing <code class="notranslate">DifferFactory</code> as a multi provider would be better, but this could work without changing existing APIs.</sub></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Injectable()
class CustomIterableDiffers implements IterableDiffers {
  constructor(private differs: IterableDiffers) {}

  get factories(): IterableDifferFactory[] { return this.differs.factories }

  find(iterable: any): IterableDifferFactory {
    if (iterable[SOME_SPECIAL_TOKEN]) {
      return superPerformantDifferFactory
    }
    return this.differs.find(iterable)
  }
}

@NgModule({
  providers: [
    { provide: IterableDiffers, useClass: CustomIterableDiffers, intercept: true }
  ]
})
class AppModule { }"><pre class="notranslate">@<span class="pl-smi">Injectable</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">CustomIterableDiffers</span> <span class="pl-k">implements</span> <span class="pl-smi">IterableDiffers</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">private</span> <span class="pl-s1">differs</span>: <span class="pl-smi">IterableDiffers</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>

  <span class="pl-k">get</span> <span class="pl-en">factories</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">IterableDifferFactory</span><span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">differs</span><span class="pl-kos">.</span><span class="pl-c1">factories</span> <span class="pl-kos">}</span>

  <span class="pl-en">find</span><span class="pl-kos">(</span><span class="pl-s1">iterable</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-smi">IterableDifferFactory</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">iterable</span><span class="pl-kos">[</span><span class="pl-smi">SOME_SPECIAL_TOKEN</span><span class="pl-kos">]</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-s1">superPerformantDifferFactory</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">differs</span><span class="pl-kos">.</span><span class="pl-en">find</span><span class="pl-kos">(</span><span class="pl-s1">iterable</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">IterableDiffers</span><span class="pl-kos">,</span> <span class="pl-c1">useClass</span>: <span class="pl-smi">CustomIterableDiffers</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span></pre></div>
<p dir="auto">Custom control over existing strategy:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="const disabledInterceptors = new WeakMap&lt;HttpRequest, Set&lt;Type&lt;HttpInterceptor&gt;&gt;&gt;()

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useFactory: enableFiltering, multi: true, intercept: true },
    InterceptorControlService,
  ]
})
class AppModule { }

function enableFiltering(interceptors: HttpInterceptor) {
  return interceptors.map(interceptor =&gt; ({
    intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; {
      if (disabledInterceptors.has(req) &amp;&amp; disabledInterceptors.get(req).has(interceptor.constructor)) {
        return next.handle(req)
      }
      return next.handle(interceptor.intercept(req, next))
    }
  }))
}

@Injectable()
class InterceptorControlService {
  disable(request: HttpRequest, interceptorType: Type&lt;HttpInterceptor&gt;) {
    if (!disabledInterceptors.has(request)) {
      disabledInterceptors.set(request, new Set())
    }
    disabledInterceptors.get(request).add(interceptorType)
  }
}

@Component({ /*...*/ })
class MyComponent {
  constructor(http: HttpClient, interceptorControl: InterceptorControlService) {
    const request = http.post(/*...*/)
    interceptorControl.disable(request, SomeCustomInterceptor)
    request.subscribe(/*...*/)
  }
}"><pre class="notranslate"><span class="pl-k">const</span> <span class="pl-s1">disabledInterceptors</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">WeakMap</span><span class="pl-kos">&lt;</span><span class="pl-smi">HttpRequest</span><span class="pl-kos">,</span> <span class="pl-smi">Set</span><span class="pl-kos">&lt;</span><span class="pl-smi">Type</span><span class="pl-kos">&lt;</span><span class="pl-smi">HttpInterceptor</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span>

@<span class="pl-smi">NgModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">providers</span>: <span class="pl-kos">[</span>
    <span class="pl-kos">{</span> <span class="pl-c1">provide</span>: <span class="pl-smi">HTTP_INTERCEPTORS</span><span class="pl-kos">,</span> <span class="pl-c1">useFactory</span>: <span class="pl-s1">enableFiltering</span><span class="pl-kos">,</span> <span class="pl-c1">multi</span>: <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">intercept</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-smi">InterceptorControlService</span><span class="pl-kos">,</span>
  <span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">AppModule</span> <span class="pl-kos">{</span> <span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">enableFiltering</span><span class="pl-kos">(</span><span class="pl-s1">interceptors</span>: <span class="pl-smi">HttpInterceptor</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s1">interceptors</span><span class="pl-kos">.</span><span class="pl-en">map</span><span class="pl-kos">(</span><span class="pl-s1">interceptor</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-en">intercept</span><span class="pl-kos">(</span><span class="pl-s1">req</span>: <span class="pl-smi">HttpRequest</span><span class="pl-kos">&lt;</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">next</span>: <span class="pl-smi">HttpHandler</span><span class="pl-kos">)</span>: <span class="pl-smi">Observable</span><span class="pl-kos">&lt;</span><span class="pl-smi">HttpEvent</span><span class="pl-kos">&lt;</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">disabledInterceptors</span><span class="pl-kos">.</span><span class="pl-en">has</span><span class="pl-kos">(</span><span class="pl-s1">req</span><span class="pl-kos">)</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">disabledInterceptors</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s1">req</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">has</span><span class="pl-kos">(</span><span class="pl-s1">interceptor</span><span class="pl-kos">.</span><span class="pl-c1">constructor</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-s1">next</span><span class="pl-kos">.</span><span class="pl-en">handle</span><span class="pl-kos">(</span><span class="pl-s1">req</span><span class="pl-kos">)</span>
      <span class="pl-kos">}</span>
      <span class="pl-k">return</span> <span class="pl-s1">next</span><span class="pl-kos">.</span><span class="pl-en">handle</span><span class="pl-kos">(</span><span class="pl-s1">interceptor</span><span class="pl-kos">.</span><span class="pl-en">intercept</span><span class="pl-kos">(</span><span class="pl-s1">req</span><span class="pl-kos">,</span> <span class="pl-s1">next</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">Injectable</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">InterceptorControlService</span> <span class="pl-kos">{</span>
  <span class="pl-en">disable</span><span class="pl-kos">(</span><span class="pl-s1">request</span>: <span class="pl-smi">HttpRequest</span><span class="pl-kos">,</span> <span class="pl-s1">interceptorType</span>: <span class="pl-smi">Type</span><span class="pl-kos">&lt;</span><span class="pl-smi">HttpInterceptor</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-s1">disabledInterceptors</span><span class="pl-kos">.</span><span class="pl-en">has</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-s1">disabledInterceptors</span><span class="pl-kos">.</span><span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">,</span> <span class="pl-k">new</span> <span class="pl-smi">Set</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
    <span class="pl-s1">disabledInterceptors</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">add</span><span class="pl-kos">(</span><span class="pl-s1">interceptorType</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/*...*/</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">http</span>: <span class="pl-smi">HttpClient</span><span class="pl-kos">,</span> <span class="pl-s1">interceptorControl</span>: <span class="pl-smi">InterceptorControlService</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">request</span> <span class="pl-c1">=</span> <span class="pl-s1">http</span><span class="pl-kos">.</span><span class="pl-en">post</span><span class="pl-kos">(</span><span class="pl-c">/*...*/</span><span class="pl-kos">)</span>
    <span class="pl-s1">interceptorControl</span><span class="pl-kos">.</span><span class="pl-en">disable</span><span class="pl-kos">(</span><span class="pl-s1">request</span><span class="pl-kos">,</span> <span class="pl-smi">SomeCustomInterceptor</span><span class="pl-kos">)</span>
    <span class="pl-s1">request</span><span class="pl-kos">.</span><span class="pl-en">subscribe</span><span class="pl-kos">(</span><span class="pl-c">/*...*/</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<h4 dir="auto">Implementation</h4>
<p dir="auto">Each <code class="notranslate">Injector</code> should hold a internal slot of interceptors, a naive logical demo could be:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// Didn't consider `multi: true` yet
class Injector_ {
  private interceptedInjectables = new Map&lt;/*token*/any, /*instance*/any&gt;()
  private providerInterceptors = new Map&lt;/*token*/any, /*interceptors*/Provider[]&gt;()

  hasInterceptors(token: any) {
    return this.providerInterceptors.has(token) || (!this.hasLocalProvider(token) &amp;&amp; this.parent.hasInterceptors(token))
  }

  getInterceptors(token: any) {
    return [...(this.hasLocalProvider(token) ? [] : this.parent.getInterceptors(token)), this.providerInterceptors.get(token)]
  }

  get(token: any) {
    if (this.interceptedInjectables.has(token)) {
      return this.interceptedInjectables.get(token)
    }
    if (this.hasInterceptors(token)) {
      const raw = getRawProviderSomehow(token)
      const interceptors = this.getInterceptors(token)
      const res = interceptors.reduce(
        (previousInstance, currentProvider) =&gt; instantiateSomehow(currentProvider, previousInstance), raw)
      this.interceptedInjectables.set(token, res)
      return res
    }
    // original logic
  }
}"><pre class="notranslate"><span class="pl-c">// Didn't consider `multi: true` yet</span>
<span class="pl-k">class</span> <span class="pl-smi">Injector_</span> <span class="pl-kos">{</span>
  <span class="pl-k">private</span> <span class="pl-c1">interceptedInjectables</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Map</span><span class="pl-kos">&lt;</span><span class="pl-c">/*token*/</span><span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-c">/*instance*/</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span>
  <span class="pl-k">private</span> <span class="pl-c1">providerInterceptors</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Map</span><span class="pl-kos">&lt;</span><span class="pl-c">/*token*/</span><span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-c">/*interceptors*/</span><span class="pl-smi">Provider</span><span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span>

  <span class="pl-en">hasInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">providerInterceptors</span><span class="pl-kos">.</span><span class="pl-en">has</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span> <span class="pl-c1">||</span> <span class="pl-kos">(</span><span class="pl-c1">!</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">hasLocalProvider</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">parent</span><span class="pl-kos">.</span><span class="pl-en">hasInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span>

  <span class="pl-en">getInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-kos">[</span>...<span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">hasLocalProvider</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span> ? <span class="pl-kos">[</span><span class="pl-kos">]</span> : <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">parent</span><span class="pl-kos">.</span><span class="pl-en">getInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">providerInterceptors</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span><span class="pl-kos">]</span>
  <span class="pl-kos">}</span>

  <span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s1">token</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">interceptedInjectables</span><span class="pl-kos">.</span><span class="pl-en">has</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">return</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">interceptedInjectables</span><span class="pl-kos">.</span><span class="pl-en">get</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">hasInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
      <span class="pl-k">const</span> <span class="pl-s1">raw</span> <span class="pl-c1">=</span> <span class="pl-en">getRawProviderSomehow</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span>
      <span class="pl-k">const</span> <span class="pl-s1">interceptors</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">getInterceptors</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">)</span>
      <span class="pl-k">const</span> <span class="pl-s1">res</span> <span class="pl-c1">=</span> <span class="pl-s1">interceptors</span><span class="pl-kos">.</span><span class="pl-en">reduce</span><span class="pl-kos">(</span>
        <span class="pl-kos">(</span><span class="pl-s1">previousInstance</span><span class="pl-kos">,</span> <span class="pl-s1">currentProvider</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">instantiateSomehow</span><span class="pl-kos">(</span><span class="pl-s1">currentProvider</span><span class="pl-kos">,</span> <span class="pl-s1">previousInstance</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-s1">raw</span><span class="pl-kos">)</span>
      <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">interceptedInjectables</span><span class="pl-kos">.</span><span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">token</span><span class="pl-kos">,</span> <span class="pl-s1">res</span><span class="pl-kos">)</span>
      <span class="pl-k">return</span> <span class="pl-s1">res</span>
    <span class="pl-kos">}</span>
    <span class="pl-c">// original logic</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>For performance consideration (static ones):</strong></p>
<ul dir="auto">
<li>To get rid of mapping, the <code class="notranslate">interceptors</code> slot should be directly added to <code class="notranslate">providerDef</code> instance via <code class="notranslate">Compiler</code>;</li>
<li>If an injector has only <strong>provider interceptor</strong> but not <strong>concrete provider</strong>, use a <code class="notranslate">providerDef</code> with value of special symbol <code class="notranslate">NO_VALUE</code> to ship <code class="notranslate">interceptors</code>;</li>
</ul>
<p dir="auto"><strong>Tree-shakable consideration (static ones):</strong></p>
<p dir="auto">Extend <code class="notranslate">@Inject()</code> decorator to accept an additional optional parameter:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({ /*...*/ })
class MyComponent {
  constructor(
    @Inject(HttpClient, logRequest) http: HttpClient
  ) {}
}

// makeParamDecorator('Inject', (token: any, ...interceptors: any[]) =&gt; ({token, interceptors}))"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/*...*/</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span>
    @<span class="pl-smi">Inject</span><span class="pl-kos">(</span><span class="pl-smi">HttpClient</span><span class="pl-kos">,</span> <span class="pl-s1">logRequest</span><span class="pl-kos">)</span> <span class="pl-s1">http</span>: <span class="pl-smi">HttpClient</span>
  <span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-c">// makeParamDecorator('Inject', (token: any, ...interceptors: any[]) =&gt; ({token, interceptors}))</span></pre></div>
<p dir="auto">Or introduce a new decorator:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component({ /*...*/ })
class MyComponent {
  constructor(
    @Intercept(logRequest) http: HttpClient
  ) {}
}

// makeParamDecorator('Intercept', (...interceptors: any[]) =&gt; ({interceptors}))"><pre class="notranslate">@<span class="pl-smi">Component</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c">/*...*/</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-k">class</span> <span class="pl-smi">MyComponent</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span>
    @<span class="pl-smi">Intercept</span><span class="pl-kos">(</span><span class="pl-s1">logRequest</span><span class="pl-kos">)</span> <span class="pl-s1">http</span>: <span class="pl-smi">HttpClient</span>
  <span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-c">// makeParamDecorator('Intercept', (...interceptors: any[]) =&gt; ({interceptors}))</span></pre></div>
<p dir="auto">Child injectors should not be affected in this way.</p>
<h2 dir="auto">Minimal reproduction of the problem with instructions</h2>

<p dir="auto">Could go to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="209202050" data-permission-text="Title is private" data-url="https://github.com/angular/angular/issues/14620" data-hovercard-type="issue" data-hovercard-url="/angular/angular/issues/14620/hovercard" href="https://github.com/angular/angular/issues/14620">#14620</a> for repro of current behavior.</p>
<h2 dir="auto">What is the motivation / use case for changing the behavior?</h2>

<p dir="auto"><del>Provide a demo of how to raise concrete feature request</del></p>
<p dir="auto">Make the DI mechanism more powerful and useful.</p>
<h2 dir="auto">Environment</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="
Angular version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:
"><pre class="notranslate"><code class="notranslate">
Angular version: X.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

</code></pre></div>