Repository: TypeScript
Issue: mixing generics, Pick, Exclude and intersection types fails to compile in 3.1.0
Labels: Bug,Domain: Indexed Access Types

<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨

Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Even if you think you've found a *bug*, please read the FAQ first, especially the Common "Bugs" That Aren't Bugs section!

Please help us by doing the following steps before logging an issue:
  * Search: https://github.com/Microsoft/TypeScript/search?type=Issues
  * Read the FAQ: https://github.com/Microsoft/TypeScript/wiki/FAQ

Please fill in the *entire* template below.
-->

<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:**  3.2.0-dev.20181031

<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:** generic pick exclude keyof intersection spread

**Code**

```ts
type TWithFoo<T> = Pick<T, Exclude<keyof T, "foo">> & { foo: string };

const foobar: TWithFoo<{ foo: number; bar: string }> = {
  foo: "foo",
  bar: "bar",
};

function strictSpread<T, K extends keyof T>(
  original: T,
  override: Pick<T, K> | T
): T {
  return Object.assign({}, original, override);
}

// Works as expected.
strictSpread(foobar, {
  foo: "foo",
  bar: "bar",
});

// Fails as expected.
strictSpread(foobar, {
  baz: "foo",
});

function fn<T extends object>() {
  const o: TWithFoo<T> = null as any;
  // Fails unexpectedly.
  strictSpread(o, {
    foo: "foo",
  });
}
```

**Expected behavior:**

The line annotated "fails unexpectedly" should compile successfully.

AFAICT this change happened between `3.1.0-dev.20180825` and `3.1.0-dev.20180828`.

**Actual behavior:**

The line annotated "fails unexpectedly" does not compile, though it used to in earlier versions.

The error reported is

```
Type '"foo"' is not assignable to type 'T["foo"] & string'.
  Type '"foo"' is not assignable to type 'T["foo"]'.
```

But `TWithFoo` is specifically defined to ignore any existing `foo` key and replace it with `string`.

**Playground Link:** [link](https://www.typescriptlang.org/play/index.html#src=type%20TWithFoo%3CT%3E%20%3D%20Pick%3CT%2C%20Exclude%3Ckeyof%20T%2C%20%22foo%22%3E%3E%20%26%20%7B%20foo%3A%20string%20%7D%3B%0D%0A%0D%0Aconst%20foobar%3A%20TWithFoo%3C%7B%20foo%3A%20number%3B%20bar%3A%20string%20%7D%3E%20%3D%20%7B%0D%0A%20%20foo%3A%20%22foo%22%2C%0D%0A%20%20bar%3A%20%22bar%22%2C%0D%0A%7D%3B%0D%0A%0D%0Afunction%20strictSpread%3CT%2C%20K%20extends%20keyof%20T%3E(%0D%0A%20%20original%3A%20T%2C%0D%0A%20%20override%3A%20Pick%3CT%2C%20K%3E%20%7C%20T%0D%0A)%3A%20T%20%7B%0D%0A%20%20return%20Object.assign(%7B%7D%2C%20original%2C%20override)%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F%20Works%20as%20expected.%0D%0AstrictSpread(foobar%2C%20%7B%0D%0A%20%20foo%3A%20%22foo%22%2C%0D%0A%20%20bar%3A%20%22bar%22%2C%0D%0A%7D)%3B%0D%0A%0D%0A%2F%2F%20Fails%20as%20expected.%0D%0AstrictSpread(foobar%2C%20%7B%0D%0A%20%20baz%3A%20%22foo%22%2C%0D%0A%7D)%3B%0D%0A%0D%0A%2F%2F%20Fails%20unexpectedly.%0D%0Afunction%20fn%3CT%20extends%20object%3E()%20%7B%0D%0A%20%20const%20o%3A%20TWithFoo%3CT%3E%20%3D%20null%20as%20any%3B%0D%0A%20%20strictSpread(o%2C%20%7B%0D%0A%20%20%20%20foo%3A%20%22foo%22%2C%0D%0A%20%20%7D)%3B%0D%0A%7D)

**Related Issues:** #27201, #27928