-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1-tuple of union should be the same as union of 1-tuples #30895
Comments
This is at best only true under a full unification algorithm. As-is, this would be a substantial breaking change since: const arr1: [string] | [number] = ["0" as any];
const arr2: [string | number] = ["0" as any];
const k1 = arr1.filter(e => e === "0");
const k2 = arr2.filter(e => e === "0"); |
You're right, didn't think of that. Still I think the code in Use Cases should work, I'm just not sure how to achieve that reasonably. Could we, for example, infer the type of 1-tuple literals to be either union-of-tuple or tuple-of-union depending on the context? declare let value: string | number;
let a = [value]; // [string | number] as before
let b: [string | number] = [value]; // works
let c: [string] | [number] = [value]; // also works Or is the idea dumb on a fundamental level and should I abandon it and rather summon |
The code in "Use Cases" already works? Anyway I think the "right fix" is a sort of combinatorial assignability reasoning that considers all possible expansion forms of a source type and sees if they have a corresponding valid assignment target. IOW in theory |
Okay, I did too much posting and not enough testing :) function fn(patterns: string | string[] | RegExp | RegExp[]): void
{
// I have to uncomment the assertion or else it throws
if (!Array.isArray(patterns)) patterns = [patterns] // as [string]|[RegExp];
} But it seems that I'd better close this issue and open a more specific one about that precise problem. |
The inferred type of function fn(patterns: string | string[] | RegExp | RegExp[]): void
{
if (!Array.isArray(patterns)) {
// k: Array<string | RegExp>
const k = [patterns];
// therefore these are both valid
k.push("");
k.push(/expr/);
// Writes a heterogeneous array where a homogeneous one is expected
patterns = k;
}
} |
Somewhat awkwardly, this is legal 🙃 patterns = typeof patterns === "string" ? [patterns] : [patterns]; |
This is probably fixed by #30779 since a union of tuples should be a discriminated union. |
Search Terms
Union of singletons vs singleton of union, one-element array, single-value array, singleton.
Intersection of 1-tuples should be the same as 1-tuple of the intersection.
Suggestion
As a 1-tuple, or single-element array, contains only one wrapped value, the exact same type operations that are applied to them also apply to their elements. That is, saying "a 1-tuple containing either A or B" is the same as saying "either a 1-tuple containing A, or a 1-tuple containing B". This applies both to type unions and type intersections.
This all should be true in TypeScript:
Use Cases
Examples
See Use Cases, I couldn't come up with another example that would be different enough to be worth mentioning.
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: