facebook / flow

Adds static typing to JavaScript to improve developer productivity and code quality.

Home Page:https://flow.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to annotate a function that can take an array consisting of strings and or functions?

faceleg opened this issue · comments

I am building an interface for AngularJS. My initial work on the interface is below:

declare class AngularJSModule {
  controller(name: string, dependencies: Array<Function | string>): AngularJSModule;
}

declare class AngularJS {
  module(name: string, dependencies: Array<string>): AngularJSModule ;
}

declare var angular: AngularJS;

And some sample code:

/* @flow */
angular.module('testModule', ['dep1', 'dep2', 'dep3'])
.controller('CapacityProfileViewController', ['$scope', '$window', '$routeParams', '$location', 'modal',
 function($scope, $window, $routeParams, $location, modal) {
}]);

The error produced:


example.js:4:2,5:1: function
This type is incompatible with
  flow-interfaces-angular/interfaces/angular.js:6:59,64: string

flow-interfaces-angular/interfaces/angular.js:6:48,55: function type
Too few arguments (expected default/rest parameters in function)
  example.js:4:2,5:1: function

Found 2 errors

Interesting. This works with one argument:

/* @flow */
angular.module('testModule', ['dep1', 'dep2', 'dep3'])
.controller('CapacityProfileViewController', ['$scope', '$window', '$routeParams', '$location', 'modal',
 function($scope) { // <- only one argument
}]);

But rest params doesn't help:

declare class AngularJSModule {
  controller(name: string, dependencies: Array<string | ((...w: Array<any>) => any)>): AngularJSModule;
}

/* @flow */
angular.module('testModule', ['dep1', 'dep2', 'dep3'])
.controller('CapacityProfileViewController', ['$scope', '$window', '$routeParams', '$location', 'modal',
 function($scope, $window, $routeParams, $location, modal) {
}]);

It fails with the same error Too few arguments (expected default/rest parameters in function).

So the only solution I've come up:

angular.module('testModule', ['dep1', 'dep2', 'dep3'])
.controller('CapacityProfileViewController', ['dep1', 'dep2', function(...deps: Array<any>): any {
var $scope = deps[0];
var $window =  deps[1];
// etc
}
]);

It doesn't seem right, so I'm interested too what's the best way except Typescript-way ( controller(name: string, dependencies: Array<any>)).

Thanks @UnknownException for posting your additional research.

With my limited knowledge of flow, this seems like a bug.

Also noting that I must use vanilla JS in my projects.

👍 this is a great point. Fixing this would open a lot of doors to Angular 1.X

Has this been fixed as part of #256?

The original code example no longer produces type errors for me. Please reopen if this is still an issue.