You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
1-tuple of union should be the same as union of 1-tuples #30895
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:
[A|B|C]===[A|B]|[C]===[A]|[B]|[C][A|B]&[C]===[(A|B)&C]===([A]|[B])&[C]// where A === B means both A is assignable to B and B is assignable to A[A|B|C]⊂Array<A|B|C>[A|B|C]⊂A[]|B[]|C[]// where A ⊂ B means A is assignable to B, but B is not assignable to A
Use Cases
typevalue=string|number;typearray=string[]|number[];function(a: value|array){constarr=Array.isArray(a) ? a : [a];// this should work}
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:
This wouldn't be a breaking change in existing TypeScript/JavaScript code
This wouldn't change the runtime behavior of existing JavaScript code
This could be implemented without emitting different JS based on the types of the expressions
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
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?
declareletvalue: string|number;leta=[value];// [string | number] as beforeletb: [string|number]=[value];// worksletc: [string]|[number]=[value];// also works
Or is the idea dumb on a fundamental level and should I abandon it and rather summon as any every time I'd use something like that?
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 [string | number, string | number]should be assignable to [string, string] | [number, number] | [string, number] | [number, string].
Okay, I did too much posting and not enough testing :)
The code I had problem with was this:
functionfn(patterns: string|string[]|RegExp|RegExp[]): void{// I have to uncomment the assertion or else it throwsif(!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 [patterns] says this is allowed:
functionfn(patterns: string|string[]|RegExp|RegExp[]): void{if(!Array.isArray(patterns)){// k: Array<string | RegExp>constk=[patterns];// therefore these are both validk.push("");k.push(/expr/);// Writes a heterogeneous array where a homogeneous one is expectedpatterns=k;}}
Activity
RyanCavanaugh commentedon Apr 12, 2019
This is at best only true under a full unification algorithm. As-is, this would be a substantial breaking change since:
cshaa commentedon Apr 12, 2019
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?
Or is the idea dumb on a fundamental level and should I abandon it and rather summon
as anyevery time I'd use something like that?RyanCavanaugh commentedon Apr 12, 2019
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
[string | number, string | number]should be assignable to[string, string] | [number, number] | [string, number] | [number, string].cshaa commentedon Apr 12, 2019
Okay, I did too much posting and not enough testing :)
The code I had problem with was this:
But it seems that I'd better close this issue and open a more specific one about that precise problem.
RyanCavanaugh commentedon Apr 12, 2019
The inferred type of
[patterns]says this is allowed:RyanCavanaugh commentedon Apr 12, 2019
Somewhat awkwardly, this is legal 🙃
weswigham commentedon Apr 12, 2019
This is probably fixed by #30779 since a union of tuples should be a discriminated union.