I have a class method which accepts a single argument as a string and returns an object which has the matching `type` property. This method is used to narrow a discriminated union type down, and guarantees that the returned object will always be of the particular narrowed type which has the provided `type` discriminate value.

I'm trying to provide a type signature for this method that will correctly narrow the type down from a generic param, but nothing I try narrows it down from the discriminated union without the user explicitly providing the type it should be narrowed down to. That works, but is annoying and feels quite redundant.

Hopefully this minimum reproduction makes it clear:

```ts
interface Action {
  type: string;
}

interface ExampleAction extends Action {
  type: 'Example';
  example: true;
}

interface AnotherAction extends Action {
  type: 'Another';
  another: true;
}

type MyActions = ExampleAction | AnotherAction;

declare class Example<T extends Action> {
  // THIS IS THE METHOD IN QUESTION
  doSomething<R extends T>(key: R['type']): R;
}

const items = new Example<MyActions>();

// result is guaranteed to be an ExampleAction
// but it is not inferred as such
const result1 = items.doSomething('Example');

// ts: Property 'example' does not exist on type 'AnotherAction'
console.log(result1.example);

/**
 * If the dev provides the type more explicitly it narrows it
 * but I'm hoping it can be inferred instead
 */

// this works, but is not ideal
const result2 = items.doSomething<ExampleAction>('Example');
// this also works, but is not ideal
const result3: ExampleAction = items.doSomething('Example');

```

I also tried getting clever, attempting to build up a "mapped type" dynamically--which is a fairly new feature in TS.

```ts
declare class Example2<T extends Action> {
  doSomething<R extends T['type'], TypeMap extends { [K in T['type']]: T }>(key: R): TypeMap[R];
}

```

This suffers from the same outcome: it doesn't narrow the type because in the type map `{ [K in T['type']]: T }` the value for each computed property, `T`, is not *for each property of the `K in` iteration* but is instead just the same `MyActions` union. If I require the user provide a predefined mapped type I can use, that would work but this is not an option as in practice it would be a very poor developer experience. (the unions are huge)

---

This use case might seem weird. I tried to distill my issue into a more consumable form, but my use case is actually regarding Observables. If you're familiar with them, I'm trying to more accurately type the [`ofType` operator provided by redux-observable](https://github.com/redux-observable/redux-observable/blob/master/index.d.ts#L28). It is basically a shorthand for a [`filter()` on the `type` property](https://github.com/redux-observable/redux-observable/blob/master/src/ActionsObservable.js#L26-L40).

This is actually super similar to how `Observable#filter` and `Array#filter` also narrow the types, but TS seems to figure that out because the predicate callbacks have the `value is S` return value. It's not clear how I could adapt something similar here.