镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

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

Description

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.

Activity

  1. zpdDG4gta8XKpMCd commented on Jun 16, 2016

    @zpdDG4gta8XKpMCd

    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 ..*/);
    
  2. mhegazy commented on Jun 16, 2016

    @mhegazy
    Contributor

    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.

  3. iskiselev commented on Jun 17, 2016

    @iskiselev

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

  4. kitsonk commented on Jun 17, 2016

    @kitsonk
    Contributor

    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);
  5. DanielRosenwasser commented on Jun 18, 2016

    @DanielRosenwasser
    Member

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

  6. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions