Skip to content
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

Inference of [a,b] to union type array is missing index signature [0]:A and [1]:B #9216

Closed
hansmaad opened this issue Jun 16, 2016 · 5 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@hansmaad
Copy link

When calling a method declared as all<T1, T2>(values: [T1, T2]); I cannot use a union type array.

TypeScript Version:

1.8.10

Code
OK:

$q.all([a, b]).then(/*...*/);

Error:

var promises = [a, b];
$q.all(promises).then(/*...*/);

> TS2329 Index signature is missing in type '(IPromise<A> | IPromise<B>)[]'

Expected behavior:
It would be nice if both versions work, without explicitly reference types A and B. I think the problem is, that [a, b] infers to (A|B)[] instead of [A,B], which should prevent me from [a,b].push(new C()) (Is this the intension?). The problem is, that (A|B)[] looses the indexers [0]: A and [1]: B. I think that's what the error message wants to say?
Would it be possible to infer [a, b] to something like (A|B)[A, B] which is compatible to

interface IAB {
    [i:number]: A|B;
    [0]:A;
    [1]:B;
}

Btw. the error message is rather confusing, since (A|B)[] actually has an index signature.

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Jun 16, 2016

it's a well known annoying problem with tuples among many others,
it doesn't work the way you expect because array literals are inferred being array-types not tuple-types

a workaround i use:

function of2<a, b>(one: a, two: b) : [a, b] {
   return [one, two];
}
...
var promises = of2(a, b);
$q.all(promises).then(/*.. here comes tuple ..*/);

@mhegazy
Copy link
Contributor

mhegazy commented Jun 16, 2016

As noted by @Aleksey-Bykov, the compiler can not infer any array literal as a tuple, as this would be a massive breaking change. so by the time we get to the call, promises is just an array or variable length.

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jun 16, 2016
@iskiselev
Copy link

Could it infer type to (A|B)[] & [A,B] which should not be a breaking change? Or have I missed something?

@kitsonk
Copy link
Contributor

kitsonk commented Jun 17, 2016

Seems to be effective:

const a = 1;
const b = 'string';

const p: (number | string)[] & [ number, string ] = [a, b];

function all<T1, T2>(values: [T1, T2]): [T1, T2] {
    return;
}

function some<T>(values: T[]): T {
    return;
}

const r1 = all(p);
const r2 = some(p);

@DanielRosenwasser
Copy link
Member

If you inferred that, you wouldn't be able to assign a string to p[0], which (number | string)[] does allow.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

6 participants