Repository: TypeScript
Issue: Regression in 4.8 where string union type widens to string
Labels: Bug,Fix Available,Rescheduled,Has Repro

# Bug Report

### 🔎 Search Terms

`string union widening`, `string union regression`, `union widening`

### 🕗 Version & Regression Information

This regression occurred in 4.8.0, and can be reproduced with the `4.8.0-beta`, and nightly (`4.9.0-dev.20220904`) tag in TS Playground. This works with `4.7.4`.

- This changed between versions 4.7.4 and 4.8.0-beta

I feel like this might be related to the [Improved inference from binding patterns](https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#improved-inference-from-binding-patterns) change

### ⏯ Playground Link

[Playground link with relevant code](https://www.typescriptlang.org/play?ts=4.7.4#code/JYOwLgpgTgZghgYwgAgOIFc5QCYB4AqAfMgN4BQylyAFAG5wA2AXMuiANYgD2A7iAJQt6DZMADOyfAG4yAXzJkwATwAOKAPIAjAFYQEYDFjxFkAXlIUqAbXYQlokMltKuMSQF0WhnARt33hDKyMmQwbPrAXI7iWrr6dIwsbJy8AkKMohIASnpcPmJgUKAA5gA0rBzcfMTkVMhQEGDoUI7CyACEpuZs2BAwoBDYyABkw8htneYg6Awio8jKaq7jGV3mAORcOnpg6yNj7QCCUFBwSgB04senSgkM-EEKYSARUZmxO+owAMoAFnBqAiEaiWSjCdAQJKVVKlUHIMT-NQsD76bzGQiwwQrBgQzKSCx1YBuajtGLbeLgiD8fgEupUBpNFrIeAMMQQGR1eR1BiNbHAbB-AEocyFCEhOowPI0BBRApOOwOeGIqm0unIGUgOXFTA4MxKoV+JTuDlq0TE7VGfYdC04O4Qw3uamq02UBnNRwstkmtVcqjyOFupnCfmCtSPULhMCRRwIBpwSAogw69HUG3YZHkpNGIE02r0xrumjCKEpPhYtrifGmYhkuJgL6hiB3cpph5yJ6R6PIOBiAAywEgpwYBGQEAAHpAQNgJNQCkUQMVkAAfZCaLhcHlwRwr6YAW000H4VgC1HOZ4YA+gjDELHwuYDBaZdxLVTS2Lx+Cse4PUHcZhqcJ1IGjgXoO16XC8OK9GIdzdhIn7ftAjresgwTtmQAD0GHIN8EAoIsKDLAABuIADqeTsCURHIAAtEqXAzEMoAIFB+G-PhqgoM4cHdhUXbLHOJRiGQGpymRFElHqsYQPGECJmi1B5pQBEsD2-ZgQw1DrGA7Fsus5TrAiDEMNg+nIOsB5mescBWWw0brPwsKyG2QA)

To reproduce, hover over the "isWorking" variable to see that the type definition includes a union of the strings. Switch to 4.8.0-beta, and note that the type definition is now just `string`.

### 💻 Code

```ts repro
interface Guard<T> {
    (val: unknown): val is T;
}

type ObjectGuard<T> = {
    [key in keyof T]: Guard<T[key]>;
};

function isObject(val: unknown): val is Record<string, unknown> {
    return val !== undefined && val !== null && typeof val === 'object' && !Array.isArray(val);
}

function isObjectOfShape<T>(
    value: unknown,
    shape: ObjectGuard<T>,
): value is T {
    if (!isObject(value)) {
        return false;
    }
    let validShape = true;

    for (const key in shape) {
        const guard = shape[key];
        if (guard && !guard(value[key])) {
            return false;
        }
    }

    return validShape;
}

function createObjectGuard<T>(guard: ObjectGuard<T>) {
    return (val: unknown): val is T => isObjectOfShape(val, guard);
}

function asLiteral<T extends (string | boolean | number)[]>(...literals: T) {
    return (val: unknown): val is T[number] => {
        return literals.includes(val as T[number]);
    };
}

// See type of `isWorking` - should include the type key as a union of strings
const isWorking = createObjectGuard({
//    ^?
    type: asLiteral('these', 'should', 'be', 'a', 'union'),
});
```

### 🙁 Actual behavior

String union type is widened to `string`.

### 🙂 Expected behavior

String union type remains a union, rather than widening