Repository: TypeScript
Issue: Unpredictable behavior when trying to infer a generic type from a union function parameter 
Labels: Bug,Help Wanted

### 🔎 Search Terms

"parameter generic inference", "union order", "ts2345", "union generic parameter"

### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about unions and generics though I went through it all in general

### ⏯ Playground Link

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAygrgYwRAzimwCGw4qgXigCYAGEqAH2JIEYBuAKFEigEkA7AN0wBsBLACYZsuAlAAsZShNrTJROSQDMi8YybhoAWRAAlVGAD27FBAA8AFQA0sKBAAewCOwF54SVOiw48VDt34hb1wAPjEAbwYoKBRglAAuWEZowwBrRJg7R2dXWERkNGEfKAB+KGAAJzhoDKynFzx-XkEi0TKAM15TKESAI0NDHghMdmSoACsUYwAKAEpEgAUKwwBbPlNLEMYAX3UHIwrgKARjWKgKg1OIAAkRgSGKsUwUEHYEKEsrEOmo88uTCDxX7RKg6fQoIwAz55DyFOIhYHSMH-DbhOwVZYVLSeTAAc0BMUqfHYuKg2xsTUCrRQCNmBDCkWifHaUGmAEILhCrgA6NJ0xnRY6nI5oiAYwxYnH4slPADumD4R05kNM3MmM1mY2iwAAFstZVB2BADQBRcUVaZizHYtB4iCa37bX4XHAVdh-LkAtVTdhzHbqAD0AagAANwoJErEKsTSdsQ1AdWLoAgRlBetARiBdTGbL04Ecw+jrVKCVGY2T4wwg1BZXweDwoLx5SA8OmoGBOc5gDZxrgjuxDP2IAUUJhozwQDXFTrQ5JxCGbGtcTqjm3M2wuM0giIUBoWAtDGg+L0hhZNCgAIIEX6gvQo8xoiOE6Mksk2UgkBEgqDIz2oosSjao74pGRKvuSMjiFsDB7tAB5HieEBnpAKAAELXt+v4qg+AGSraIHPuWEFzl+SJ3n+OFPmW4HvmQ0GwVAABqW7gthYhYVcZiPgIoEvrGtGfowzDQGamKsVc7HkdhXG4UBdq8URNgkUJmhQPBKDHqe54AMJiKJEriQC0jMYEhmmOoJwmEcAjYJgV6EJg8qKh62G3C4DzTOE2yNng6maUh54Xg6gohaFYXhRFgrVgAejWEqpHgzxZJACBOAIDCWWcNlYOhDlOUq95ufcYqed5SV+YhyGoKhwWRXV9WhTFNbAO0JQZcKUDZZgul5QqBUUUVHleT5amHhplU6bVDXTZFTUDgazmyvFiV4Psw5pdym1pvmNY6iAJRAA

### 💻 Code

```ts
type SuccessStatus = 200 | 201;
type InvalidStatus = 400 | 401 | 402 | 403 | 404;

type MyResponse<T, S extends SuccessStatus | InvalidStatus> = {
  status: S;
  ok: S extends SuccessStatus ? true : S extends InvalidStatus ? false : boolean;
  json(): Promise<T>;
};

export const responseHandler = async <T,>(
  response:
    | MyResponse<T, SuccessStatus>
    | MyResponse<{ errorMessage: string }, InvalidStatus>
) => {
  if (!response.ok) {
    const { errorMessage } = await response.json();
    throw new Error(errorMessage);
  }
  return response.json();
};

// `{id: string }` here can be anything, but `{ errorMessage: string }` 
// will always be present, just not necessarily with `404`, might be any InvalidStatus
type PossibleTypesA =
  | MyResponse<{ id: string }, 200>
  | MyResponse<{ errorMessage: string }, 404>;

type PossibleTypesB =
  | MyResponse<{ errorMessage: string }, 404>
  | MyResponse<{ id: string }, 200>;

type ValidResponse = MyResponse<{ id: string }, 200>;
type ErrorResponse = MyResponse<{ errorMessage: string }, 404>;
type PossibleTypesC = ErrorResponse | ValidResponse;

const dataA = await responseHandler({} as PossibleTypesA);
                                    // ^ works as expected
const dataB = await responseHandler({} as PossibleTypesB);
                                    // ^ wtf?
const dataC = await responseHandler({} as PossibleTypesC);
                                    // ^ now it works as expected... but why?
```


### 🙁 Actual behavior

`responseHandler` in the snippet above throws a `ts2345` error when a union type with a swapped order is passed as an argument. Until now I thought a union type `a | b` is equivalent to `b | a` but this doesn't seem to be the case. Curiously, this is no longer an issue if the types that are part of the union are aliased, as can be seen in example C (`dataC` and `PossibleTypesC`).

### 🙂 Expected behavior

`dataB` should not throw an error.

### Additional information about the issue

There is an even crazier example and perhaps it's a better proof that this is a bug. 

```ts
type SomeType = { id: string };

type PossibleTypesA =
  | MyResponse<{ id: string }, 200>
  | MyResponse<{ errorMessage: string }, 404>;

type PossibleTypesB =
  | MyResponse<{ errorMessage: string }, 404>
  | MyResponse<SomeType, 200>;

const dataA = await responseHandler({} as PossibleTypesA);
                                    // ^ works as expected
const dataB = await responseHandler({} as PossibleTypesB);
                                    // ^ does not work but that's why I'm reporting it
```
[Playground Link](https://www.typescriptlang.org/play/?#code/C4TwDgpgBAygrgYwRAzimwCGw4qgXigCYAGEqAH2JIEYBuAKFEigEkA7AN0wBsBLACYZsuAlAAsZShNrTJROSQDMi8YybhoAWRAAlVGAD27FBAA8AFQA0sKBAAewCOwF54SVOiw48VDt34hb1wAPjEAbwYoKBRglAAuWEZowwBrRJg7R2dXWERkNGEfKAB+KGAAJzhoDKynFzx-XkEi0TKAM15TKESAI0NDHghMdmSoACsUYwAKAEpEgAUKwwBbPlNLEMYAX3UHIwrgKARjWKgKg1OIAAkRgSGKsUwUEHYEKEsrEOmo88uTCDxX7RKg6fQoIwAz55DyFOIhYHSMH-DbhOwVZYVLSeTAAc0BMUqfHYuKg2xsTUCrRQCNmBDCkWifHaUGmAEILhCrgA6NJ0xnRY6nI5oiAYwxYnH4slPADumD4R05kNM3MmM1mY2iwAAFstZVB2BADQBRcUVaZizHYtB4iCa37bX4XHAVdh-LkAtVTdhzHbqZjQGCrCAWTQRKCCRKxCrE0m7BgaFgLQxoPi9IZhyAoACCBF+oL0KPMaKjhNjJLJNlIJARIKgyM9qPR1qlBJjcarMnEW0TgagKbTGdDmhQACF8-XGyqSy2JTaUHbo0TK+Tu3WkUWm+ZgysR5Bq2RewwTiYjgJsJg84RMPLFR6Z7cXA9puFtlBngPUyh05nRzmHUFIDgJA0CwMFAB6CCoAAPSgWUJVSPBP32CAECcAQT2FKALywCcbzvJViyfe4xVfd9P0HH9hyzVAx0A8DGKY4CoNgnDDFQQ1DCOBCKlSKBejgI5dWwAByPBZR1EA2FElY-gOYBO0VBggA)
```ts
type SomeType = { id: string };

type PossibleTypesA =
  | MyResponse<SomeType, 200>
  | MyResponse<{ errorMessage: string }, 404>;

type PossibleTypesB =
  | MyResponse<{ errorMessage: string }, 404>
  | MyResponse<SomeType, 200>;

const dataA = await responseHandler({} as PossibleTypesA);
                                    // ^ works as expected
const dataB = await responseHandler({} as PossibleTypesB);
                                    // ^ it works now???
```
[Playground Link](https://www.typescriptlang.org/play/?#code/C4TwDgpgBAygrgYwRAzimwCGw4qgXigCYAGEqAH2JIEYBuAKFEigEkA7AN0wBsBLACYZsuAlAAsZShNrTJROSQDMi8YybhoAWRAAlVGAD27FBAA8AFQA0sKBAAewCOwF54SVOiw48VDt34hb1wAPjEAbwYoKBRglAAuWEZowwBrRJg7R2dXWERkNGEfKAB+KGAAJzhoDKynFzx-XkEi0TKAM15TKESAI0NDHghMdmSoACsUYwAKAEpEgAUKwwBbPlNLEMYAX3UHIwrgKARjWKgKg1OIAAkRgSGKsUwUEHYEKEsrEOmo88uTCDxX7RKg6fQoIwAz55DyFOIhYHSMH-DbhOwVZYVLSeTAAc0BMUqfHYuKg2xsTUCrRQCNmBDCkWifHaUGmAEILhCrgA6NJ0xnRY6nI5oiAYwxYnH4slPADumD4R05kNM3MmM1mY2iwAAFstZVB2BADQBRcUVaZizHYtB4iCa37bX4XHAVdh-LkAtVTdhzHbqZjQGCrCAWTQRKCCRKxCrE0m7BgaFgLQxoPi9IZhyAoACCBF+oL0KPMwZWoc0NlIJARIKgyM9qPR1qlBJjcbJNkk4i2icDUBTaYz5ezACF87X6yrzKLzTaUHbo0SSR2ZN2C3Wiw2SyGsxBK2QewwTiYjgJsJg84RMPLFR6p7cXA9puFtlBnv3Uyh05nNLmHYKAMAoDgJAwUAHowKgAA9KBZQlVI8HffYIAQJwBCPYUoDPLAxyvG8lWLB97jFZ9X3fAcvyHXcUBHf9QPohjAIg6DIyOOCKgQw1DFlEpeIYIA)

This is pure insanity to me as the only thing I changed between these two examples is whether `PossibleTypesA` uses `SomeType` or not. It should not in any circumstance affect `dataB`, so I'm extremely confused what is happening here.