title: Is there a way to type a TypeScript method decorator to restrict the type of the method it can decorate?
body: <p>I want to write a TypeScript method decorator that can only be applied to methods with a certain type of first argument. It's a common pattern in the codebase I'm working in to pass around a request context that has handles for database, metrics, logging, etc. I'd like to write a decorator that requires one of these resources in the request context, but is otherwise agnostic to the shape of the request context.</p>
  
  <p>Here's a stylized example:</p>
  
  <pre><code>interface MyResource {
      logMetricsEtc(...args: any): void;
  }
  
  interface HasResourceINeed {
      myResource: MyResource;
  }
  
  function myDecorator&lt;TFn extends ((tContext: HasResourceINeed, ...rest: any) =&gt; any)&gt;(
      _target: object,
      key: string | symbol,
      descriptor: TypedPropertyDescriptor&lt;TFn&gt;,
  ): TypedPropertyDescriptor&lt;TFn&gt; | void {
      const originalHandler = descriptor.value!;
  
      descriptor.value = function (this: any, context: HasResourceINeed, ...inputs: any) {
          context.myResource.logMetricsEtc(...inputs);
  
          return originalHandler.apply(this, [context, ...inputs]);
      } as TFn;
  }
  </code></pre>
  
  <p>In use, with <code>strictFunctionTypes</code> enabled, this decorator causes a compile error when applied to a method that otherwise looks reasonable:</p>
  
  <pre><code>interface ServiceContext {
      myResource: MyResource;
      otherResource: {
          sendMessageEtc(msg: string): Promise&lt;void&gt;;
      };
  }
  
  class MyBusinessClass {
      // This causes a compile error, but shouldn't - the decorator will 
      // work here at runtime.
      @myDecorator
      async foo(context: ServiceContext, x: number): Promise&lt;void&gt; {
  
      }
  
      // This example MUST cause a compile error to prevent invalid 
      // usage - there's no resource available in the first arg for the
      // decorator to use.
      @myDecorator
      async bar(y: string): Promise&lt;void&gt; {
  
      }
  }
  </code></pre>
  
  <p>The undesired compile error looks like this:</p>
  
  <pre><code>Argument of type 'TypedPropertyDescriptor&lt;(context: ServiceContext, x: number) =&gt; Promise&lt;void&gt;&gt;' is not assignable to parameter of type 'TypedPropertyDescriptor&lt;(tContext: HasResourceINeed, ...rest: any) =&gt; any&gt;'.
    Types of property 'value' are incompatible.
      Type '((context: ServiceContext, x: number) =&gt; Promise&lt;void&gt;) | undefined' is not assignable to type '((tContext: HasResourceINeed, ...rest: any) =&gt; any) | undefined'.
        Type '(context: ServiceContext, x: number) =&gt; Promise&lt;void&gt;' is not assignable to type '(tContext: HasResourceINeed, ...rest: any) =&gt; any'.(2345)
  </code></pre>
  
  <p>I can't reasonably turn off <code>strictFunctionTypes</code>. Is there a way to write the decorator type to accept <code>foo</code> but reject <code>bar</code>?</p>