-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Open
Labels
BugA bug in TypeScriptA bug in TypeScriptDomain: check: Type InferenceRelated to type inference performed during signature resolution or `infer` type resolutionRelated to type inference performed during signature resolution or `infer` type resolutionFix 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 TypeScriptDomain: check: Type InferenceRelated to type inference performed during signature resolution or `infer` type resolutionRelated to type inference performed during signature resolution or `infer` type resolutionFix 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