Skip to content

Regression in 4.8 where string union type widens to string #50635

Open
@me4502

Description

@me4502

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 change

⏯ Playground Link

Playground link with relevant code

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

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

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosRescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions