-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Open
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-reprosRescheduledThis issue was previously scheduled to an earlier milestoneThis issue was previously scheduled to an earlier milestone
Milestone
Description
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
whzx5byb, byronmejia and PindaPixel
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issueHas ReproThis issue has compiler-backed repros: https://aka.ms/ts-reprosThis issue has compiler-backed repros: https://aka.ms/ts-reprosRescheduledThis issue was previously scheduled to an earlier milestoneThis issue was previously scheduled to an earlier milestone