Repository: TypeScript
Issue: Infer method name for parameter decorator
Labels: Needs Investigation

**TypeScript Version:**  3.3.3
_Tried with @next _(3.4.0-dev.201xxxxx)_ ?_ NO

**Search Terms:** type:issues infer method name parameter decorator

**Code**

```typescript
declare function Method():
{
    (t: any, m: 'method'): void;
}

declare function Parameter():
{
    (t: any, m: 'method', i: number): void;
}

class Play
{
    @Method() // err
    public another_method ( @Parameter() /* NO ERROR */ test: number ): void
    {
        throw new Error('Not yet implemented');
    }
    @Method()
    public method ( @Parameter() test: number ): void
    {
        throw new Error('Not yet implemented');
    }
}
```

**Expected behavior:** `@Parameter()` should error just as `@Method()` **when applied to `another_method()`** because the `m` parameter is typed `"method"` (which should reduced the set of method). i.e method name should be enforced.

**Actual behavior:** No error

**Playground Link:** [https://typescript-play.js.org](https://typescript-play.js.org/?experimentalDecorators=true&emitDecoratorMetadata=true#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwFkQMALHYACgEoAuAKAG874X4KMb4pUBPAGngBbTgHJBxMsBG14ANxxZgAbjoBfOnVCRYCFOmx54ABVhRxGEDGr0mrNhy68Bw+GInkRArJ1TJBAI0sZeUUVdTptAGdI42geRmZWAAEiUnJqeAB6TPhLGESWAAdkfwgsMEccUksAfXNJNngkkxgzYksMzIAqeAA5AHl4AFEAJRH+kfgunItIh18Ay3hghWAC+Fs7VlIYHAB3eFQQA6GYXasRXqr4HmJ4LEFCiBBxVAspKhU7dTsU90oqOtiqVykJ-o1mqZzB0qPBZvM-IEYMtOCE1nZNls4SRdgcjiczjgLlcMDc7g8ni8QG8QB8vqx1OEgA)

**Use case :**

I crafted a type that filters method names with the `nth` parameters iff that parameters is of the given type `T`.

[See `KeysToTypedNthParameter` definition here](https://typescript-play.js.org/#code/C4TwDgpgBAkgzgOWACwAoEMBO6C2FgSYDyAZgCrgQA8CUEAHgQHYAmcUTArjgEaEA0UMoIBiCAHxQAvFAAUUMXUYRW7AMIB7JnGCZOAY2AbMAGQCWAa2gB+KJu26DRzBmx4CmOFTGSAXHIVaBmY2BU4mQzMtcysoW1dcfEIvHyh-JggAN0IoAEo8gG0EAF0lEPYyOKhHaH8SdAAbOAgAbgAoUEg7LR09Q2MY6krglVCAbwBfaShJwVQy0fZ0JhAC0pll1eLJGQyAd3kAOmOwLESPOH95-KlJMnbO6BFwyOjLanmR1ShNtenf4qCABK-xWgkqGxWOwCKDMlyEgmOhwA+lc8tJJECHpQoABpCAgOBkDQUSAsJBoM7uQg0BbfLi8AQIqAACWhADVGpwIHBSFQxm0oEKoAUoGZWAwxUwoFYQBoSKyoMV-PAKQlqcRyJQaODBCyCuKWAxtnTQjUqobJeksoR2hNxNiupyGtzeSQqGRoWQCrL5UJiu02kGGvgoMh0HBkNMBcKfvJkQAGfy9cUAc0EyIAjMndGn0bNBcKePGk1AU0x01As+luHxMPmJvxC0L9CWa4zMBnsxxazl8gXYyw2z2O12c5g8-3G20JsHQ+XU4n-PjCcTSRBySh1UlMFQE4IF4JHn7w5GHVAAPQXqAAInQN6gAB9bzwb20Q8Ay7mK9W8QSiSSlCbpSbg7lQmYHt+lbHgqp7IOeV63veT63iwb4fiOdZLn+q6AWSapUmB+6YUyMFhhG8EtJe143voD7PjeaHvqGDJYd2K4AeuwHbh44GCKxpGUCeFEITRdEoYxN5AA)
```typescript
let hash = {
    a( _0: string, _1: string ) {},
    b( _0: string, _1: number ) {},
    c( _0: number, _1: number ) {},
    d( _0: number, _1: string ) {},
}

let string_0: KeysToTypedNthParameter<0, string, typeof hash>; // "a" | "b"
let string_1: KeysToTypedNthParameter<1, string, typeof hash>; // "a" | "d"
let number_0: KeysToTypedNthParameter<0, number, typeof hash>; // "c" | "d"
let number_1: KeysToTypedNthParameter<1, number, typeof hash>; // "c" | "d"
```
Later, I used that type to infer method name for my parameter decorator - `@Inject` - in the excerpt below, I marked the ONLY line that should error and why (but both lines actually error)

```typescript
class Test
{
    public blatantly!: boolean;
}

class Play
{
    public method(
        @Inject({ type: Test })
        @Inject({ type: Number }) // err (construtor mismatch instance type)
        test: Test,
    ): void
    {
        throw new Error( 'Not yet implemented' );
    }
}
Play;
```

Here is `@Inject` decorator definition [and complete code](https://typescript-play.js.org/?experimentalDecorators=true#code/MYewdgzgLgBAkmAVgU2FAXPJqoBkCWA1sjALwwBuI+AJjAAwwCGEMArmIWCAO5jOsEKNAWIBuAFATgAGxasAKsmgSA3hJiaYABzYAjGfmAwDTKEzBQZATwCEmPSBAzkFyQF8ps+TAAKc6zUNLV0DIxgAW2QoAAsQGgAKYK0tAAEhHATVGChrbWRMJWgYdwBKZJSYdOw0LJy8gpgAOTYIvWQAJxLSmAB6XphOroTQSCgOtigQLoj8CAizYBiYfDGLYBJc-PLKrShlDBgiqAAaCtLMKloK9V3NWI7eGDBkHhgAUQ7HjoSYAHImiBYNZoisItoXFFLMgaH8YKVJClPJ5-ExrJIJKt9h0AGZMDZYYR4IjIIIpAA8FRSAGFBgAPfZgGisangaATNDTUTIM4pAB8FSy7kw2S2jVpZRFVK0lLulX6MAAYnAABoAWXeMEw3FgyG4bAA5sspiswDjOjkYiQorF4s8mFEYABaGAQZAkAB0vQA+t6IWiDY8ODQPVAIABiaW7NX0xnMmC-BSxvXx1ljDlTDrcmAAfmeyAoFswAGlkNYIAoQAoGjQmrFfEwOg7op1yXATlhoOtkNX8uTqXyOwo+fDeXKtHBk0zWGBWu0OmPx0dF5UBXLfuYOgbooUO1E2p1MGqO6saMg6ZhJxdKNQaIitO4PFIxfAIHWYg2mzbOgB5HG95BySaKd41nA8F2XJUmhHchfkVYDzzjFk2XGNhOSzElcxgNN2TQzNP2bbEIHJeCR0wOCEIZFNWEVDg0HwcBszzAjvw6YjSK1fNCy6HpSgAbSaABdEDFCw1CSEwPEZDdSQX1LctASgNUmG0fIaErckk0Q6iYFUdwO3eGDdJgPiYGIaxTTMssQBxI4YEEwo+PM4TtOnD4sJebjOPMsQSic6zbIUQTZIabCUIzLkSU0kTdPcMhYo7XwYosaw+OE8gUrSoyXh4X4PXy7RG0IzoIEwJKelIEcFBC-IYHkisqxrd8WJbDogJisD5yHDsAAkjIANSYGQ2GUP9yVuLRTNPc9LPMmyYB6+zLzfesitYv8AKA7qFr46a6UEkdXPjcSsL2zjPM6Dw+RqkhaLAejGKipKjtYTL0uYMBUsEjsACV4pSod-s+oyNxiOZdxgfKPW9Mr4TIEcfpuuqywgZTVJhDStKoty9IMoz3jpWQ2DPck5sCjt6sUtG1MxvHrokF9BuG0acU0oyFH86x5qCsQgA) -
```typescript
const Inject: InjectLike = void 0 as unknown as InjectLike;

interface InjectLike
{
    <
        C extends ConstructorLike,
    >
    ({}: { type: C }): {
        <
            // FIXME : not enough to infer the method name - see ./__playground.ts#
            M extends ( T extends ConstructorLike ? never : KeysToTypedNthParameter<I, InstanceType<C>, T> ),
            I extends number,
            T,
        >
        ( target: T, member: M, index: I ): void;
    };
}
```