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

Incorrect type inference for array rest assignment and inability to add annotation #21519

Open
theseyi opened this issue Jan 31, 2018 · 5 comments
Labels
Bug A bug in TypeScript
Milestone

Comments

@theseyi
Copy link

theseyi commented Jan 31, 2018

TypeScript Version: 2.7.1-insiders.20180127

Search Terms: array destructuring rest assignment

Code

// A *self-contained* demonstration of the problem follows...
// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.
const [stringA, ...numbers] = ['string', 1, 2];
// const [stringA, ...numbers] = <[string, number, number]>['string', 1, 2];
// const [stringA, ...numbers]: [string, number[]] = ['string', 1, 2];
// const [stringA, ...numbers]: [string, [number, number]] = ['string', 1, 2];

Expected behavior: Expect numbers to be of type number[] rather than (string | number)[].
TS also does not allow annotating as a tuple

Actual behavior: const numbers: (string | number)[]

Playground Link: http://www.typescriptlang.org/play/index.html#src=const%20%5BstringA%2C%20...numbers%5D%20%3D%20%5B'string'%2C%201%2C%202%5D%3B%0A%2F%2F%20const%20%5BstringA%2C%20...numbers%5D%20%3D%20%3C%5Bstring%2C%20number%2C%20number%5D%3E%5B'string'%2C%201%2C%202%5D%3B%0A%2F%2F%20const%20%5BstringA%2C%20...numbers%5D%3A%20%5Bstring%2C%20number%5B%5D%5D%20%3D%20%5B'string'%2C%201%2C%202%5D%3B%0A%2F%2F%20const%20%5BstringA%2C%20...numbers%5D%3A%20%5Bstring%2C%20%5Bnumber%2C%20number%5D%5D%20%3D%20%5B'string'%2C%201%2C%202%5D%3B

Related Issues:

@mhegazy
Copy link
Contributor

mhegazy commented Jan 31, 2018

Duplicate of #3369. A tuple type is not inferred in the absence of an explicit type annotation.

you can find related discussions in #16656

@mhegazy mhegazy added the Duplicate An existing issue was already created label Jan 31, 2018
@theseyi
Copy link
Author

theseyi commented Feb 1, 2018

A tuple type is not inferred in the absence of an explicit type annotation

@mhegazy so how would the numbers rest assignment be annotated as a tuple? I believe I tried to this in the last line:

const [stringA, ...numbers]: [string, [number, number]] = ['string', 1, 2];

@mhegazy
Copy link
Contributor

mhegazy commented Feb 1, 2018

The right type should be const [stringA, ...numbers]: [string, number, number]. and numbers should be inferred correctly. that is a bug we should fix.

@mhegazy mhegazy added Bug A bug in TypeScript and removed Duplicate An existing issue was already created labels Feb 1, 2018
@mhegazy mhegazy added this to the TypeScript 2.8 milestone Feb 1, 2018
@sandangel
Copy link

I have run into this issue too with overload function

// I have tried this but it does not work
interface OperatorTuple extends Array<OperatorFunction<any, any>> {
  0: OperatorFunction<any, any>;
  1: OperatorFunction<any, any>;
  2: OperatorFunction<any, any>;
  3: OperatorFunction<any, any>;
  4: OperatorFunction<any, any>;
  5: OperatorFunction<any, any>;
  6: OperatorFunction<any, any>;
  7: OperatorFunction<any, any>;
  length: 8;
}

// this is an overload function
export function Select<A, B>(mapFn: ((state: A) => B), ...operators: OperatorFunction<any, any>[]) {
  return function(target: any, name: string): void {
    if (typeof mapFn !== 'function') {
      throw new TypeError(
        `Unexpected type '${typeof mapFn}' in select operator,` + ` expected 'function'`
      );
    }

    // trying to cast type tuple
    operators = [...operators] as OperatorTuple;

    const descriptor = Object.getOwnPropertyDescriptor(target, name);

    if (delete target[name]) {
      Object.defineProperty(target, name, {
        get() {
          const source$ = NgrxSelect.store;

          if (!source$) {
            throw new Error('NgrxSelect not connected to store!');
          }

         // I have tried this too but have failed
         if (operators.length > 8) {
            throw new Error()
         }
          
          // Error: Expect 0-9 arguments but received 1 or more
          return source$.pipe(select(mapFn), ...operators);
        },
        ...descriptor
      });
    }
  };
}

@ajafff
Copy link
Contributor

ajafff commented Jul 27, 2018

The issue in the opening post is fixed in typescript@next, maybe even 3.0.0-rc.
numbers is now of type number[].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants