Quellcode durchsuchen

Chore: noImplictAny no errors left (#18303)

* Add types and rewrite datasourceChanged to async/await
Tobias Skarhed vor 6 Jahren
Ursprung
Commit
83da3660da
63 geänderte Dateien mit 285 neuen und 211 gelöschten Zeilen
  1. 1 0
      package.json
  2. 1 0
      packages/grafana-data/src/types/data.ts
  3. 1 1
      packages/grafana-ui/src/components/Graph/Graph.tsx
  4. 1 1
      packages/grafana-ui/src/components/Input/Input.tsx
  5. 1 1
      packages/grafana-ui/src/components/SetInterval/SetInterval.tsx
  6. 1 1
      packages/grafana-ui/src/types/datasource.ts
  7. 2 2
      public/app/core/controllers/signup_ctrl.ts
  8. 20 17
      public/app/core/services/ng_react.ts
  9. 5 4
      public/app/core/services/popover_srv.ts
  10. 4 4
      public/app/core/services/util_srv.ts
  11. 1 1
      public/app/core/specs/backend_srv.test.ts
  12. 3 2
      public/app/core/specs/file_export.test.ts
  13. 1 1
      public/app/core/specs/logs_model.test.ts
  14. 5 4
      public/app/core/specs/org_switcher.test.ts
  15. 5 5
      public/app/core/specs/search.test.ts
  16. 3 3
      public/app/core/specs/search_results.test.ts
  17. 6 3
      public/app/core/specs/table_model.test.ts
  18. 6 6
      public/app/core/specs/time_series.test.ts
  19. 5 4
      public/app/core/specs/value_select_dropdown.test.ts
  20. 2 2
      public/app/core/utils/connectWithReduxStore.tsx
  21. 5 5
      public/app/core/utils/css_loader.ts
  22. 9 9
      public/app/core/utils/dag.ts
  23. 4 4
      public/app/core/utils/emitter.ts
  24. 1 1
      public/app/core/utils/errors.test.ts
  25. 2 2
      public/app/core/utils/explore.test.ts
  26. 4 4
      public/app/core/utils/explore.ts
  27. 18 13
      public/app/core/utils/file_export.ts
  28. 3 3
      public/app/core/utils/flatten.ts
  29. 23 17
      public/app/core/utils/kbn.ts
  30. 1 1
      public/app/core/utils/model_utils.ts
  31. 2 2
      public/app/core/utils/outline.ts
  32. 1 1
      public/app/core/utils/reselect.ts
  33. 2 1
      public/app/core/utils/scrollbar.ts
  34. 2 2
      public/app/core/utils/sort_by_keys.ts
  35. 1 1
      public/app/core/utils/tags.ts
  36. 10 3
      public/app/core/utils/text.ts
  37. 5 5
      public/app/core/utils/ticks.ts
  38. 2 2
      public/app/core/utils/url.ts
  39. 1 1
      public/app/features/admin/AdminEditUserCtrl.ts
  40. 1 1
      public/app/features/alerting/AlertTabCtrl.ts
  41. 1 1
      public/app/features/alerting/TestRuleResult.tsx
  42. 10 3
      public/app/features/annotations/annotation_tooltip.ts
  43. 4 3
      public/app/features/annotations/annotations_srv.ts
  44. 8 9
      public/app/features/annotations/editor_ctrl.ts
  45. 3 2
      public/app/features/annotations/event_editor.ts
  46. 6 6
      public/app/features/annotations/event_manager.ts
  47. 5 5
      public/app/features/annotations/events_processing.ts
  48. 1 1
      public/app/features/annotations/specs/annotations_srv.test.ts
  49. 6 6
      public/app/features/api-keys/ApiKeysPage.tsx
  50. 15 7
      public/app/features/dashboard/components/AdHocFilters/AdHocFiltersCtrl.ts
  51. 6 4
      public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx
  52. 8 1
      public/app/features/dashboard/components/DashExportModal/DashExportCtrl.ts
  53. 21 8
      public/app/features/dashboard/components/DashLinks/DashLinksContainerCtrl.ts
  54. 4 4
      public/app/features/dashboard/components/DashLinks/DashLinksEditorCtrl.ts
  55. 1 1
      public/app/features/dashboard/components/DashNav/DashNav.tsx
  56. 1 1
      public/app/features/dashboard/components/DashboardPermissions/DashboardPermissions.tsx
  57. 1 1
      public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx
  58. 2 2
      public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx
  59. 1 1
      public/app/features/dashboard/components/ExportDataModal/ExportDataModalCtrl.ts
  60. 2 2
      public/app/features/dashboard/state/DashboardModel.ts
  61. 1 1
      scripts/ci-frontend-metrics.sh
  62. 1 1
      tsconfig.json
  63. 6 1
      yarn.lock

+ 1 - 0
package.json

@@ -177,6 +177,7 @@
     "@types/enzyme-adapter-react-16": "1.0.5",
     "@types/file-saver": "2.0.1",
     "@types/marked": "0.6.5",
+    "@types/mousetrap": "1.6.3",
     "@types/prismjs": "1.16.0",
     "@types/react-redux": "7.0.8",
     "@types/react-table": "6.8.5",

+ 1 - 0
packages/grafana-data/src/types/data.ts

@@ -106,6 +106,7 @@ export interface AnnotationEvent {
   dashboardId?: number;
   panelId?: number;
   userId?: number;
+  regionId?: number;
   login?: string;
   email?: string;
   avatarUrl?: string;

+ 1 - 1
packages/grafana-ui/src/components/Graph/Graph.tsx

@@ -58,7 +58,7 @@ export class Graph extends PureComponent<GraphProps> {
       }),
       yAxisConfig => yAxisConfig.index
     );
-    const flotOptions = {
+    const flotOptions: any = {
       legend: {
         show: false,
       },

+ 1 - 1
packages/grafana-ui/src/components/Input/Input.tsx

@@ -27,7 +27,7 @@ export class Input extends PureComponent<Props, State> {
     className: '',
   };
 
-  state = {
+  state: State = {
     error: null,
   };
 

+ 1 - 1
packages/grafana-ui/src/components/SetInterval/SetInterval.tsx

@@ -76,7 +76,7 @@ export class SetInterval extends PureComponent<Props> {
     this.propsSubject.unsubscribe();
   }
 
-  render() {
+  render(): null {
     return null;
   }
 }

+ 1 - 1
packages/grafana-ui/src/types/datasource.ts

@@ -210,7 +210,7 @@ export abstract class DataSourceApi<
   /**
    * Get tag keys for adhoc filters
    */
-  getTagKeys?(options: any): Promise<MetricFindValue[]>;
+  getTagKeys?(options?: any): Promise<MetricFindValue[]>;
 
   /**
    * Get tag values for adhoc filters

+ 2 - 2
public/app/core/controllers/signup_ctrl.ts

@@ -34,7 +34,7 @@ export class SignUpCtrl {
       },
     };
 
-    backendSrv.get('/api/user/signup/options').then(options => {
+    backendSrv.get('/api/user/signup/options').then((options: any) => {
       $scope.verifyEmailEnabled = options.verifyEmailEnabled;
       $scope.autoAssignOrg = options.autoAssignOrg;
     });
@@ -45,7 +45,7 @@ export class SignUpCtrl {
       return;
     }
 
-    this.backendSrv.post('/api/user/signup/step2', this.$scope.formModel).then(rsp => {
+    this.backendSrv.post('/api/user/signup/step2', this.$scope.formModel).then((rsp: any) => {
       if (rsp.code === 'redirect-to-select-org') {
         window.location.href = config.appSubUrl + '/profile/select-org?signup=1';
       } else {

+ 20 - 17
public/app/core/services/ng_react.ts

@@ -12,11 +12,11 @@
 import { kebabCase } from 'lodash';
 import React from 'react';
 import ReactDOM from 'react-dom';
-import angular from 'angular';
+import angular, { auto } from 'angular';
 
 // get a react component from name (components can be an angular injectable e.g. value, factory or
 // available on window
-function getReactComponent(name, $injector) {
+function getReactComponent(name: string, $injector: auto.IInjectorService) {
   // if name is a function assume it is component and return it
   if (angular.isFunction(name)) {
     return name;
@@ -36,6 +36,7 @@ function getReactComponent(name, $injector) {
   if (!reactComponent) {
     try {
       reactComponent = name.split('.').reduce((current, namePart) => {
+        // @ts-ignore
         return current[namePart];
       }, window);
     } catch (e) {}
@@ -49,7 +50,7 @@ function getReactComponent(name, $injector) {
 }
 
 // wraps a function with scope.$apply, if already applied just return
-function applied(fn, scope) {
+function applied(fn: any, scope: any) {
   if (fn.wrappedInApply) {
     return fn;
   }
@@ -81,7 +82,7 @@ function applied(fn, scope) {
  * @param propsConfig configuration object for all properties
  * @returns {Object} props with the functions wrapped in scope.$apply
  */
-function applyFunctions(obj, scope, propsConfig?) {
+function applyFunctions(obj: any, scope: any, propsConfig?: any): object {
   return Object.keys(obj || {}).reduce((prev, key) => {
     const value = obj[key];
     const config = (propsConfig || {})[key] || {};
@@ -90,6 +91,7 @@ function applyFunctions(obj, scope, propsConfig?) {
      * ensures that when function is called from a React component
      * the Angular digest cycle is run
      */
+    // @ts-ignore
     prev[key] = angular.isFunction(value) && config.wrapApply !== false ? applied(value, scope) : value;
 
     return prev;
@@ -104,7 +106,7 @@ function applyFunctions(obj, scope, propsConfig?) {
  * Uses the watchDepth attribute to determine how to watch props on scope.
  * If watchDepth attribute is NOT reference or collection, watchDepth defaults to deep watching by value
  */
-function watchProps(watchDepth, scope, watchExpressions, listener) {
+function watchProps(watchDepth: string, scope: any, watchExpressions: any[], listener: any) {
   const supportsWatchCollection = angular.isFunction(scope.$watchCollection);
   const supportsWatchGroup = angular.isFunction(scope.$watchGroup);
 
@@ -138,24 +140,24 @@ function watchProps(watchDepth, scope, watchExpressions, listener) {
 }
 
 // render React component, with scope[attrs.props] being passed in as the component props
-function renderComponent(component, props, scope, elem) {
+function renderComponent(component: any, props: object, scope: any, elem: Element[]) {
   scope.$evalAsync(() => {
     ReactDOM.render(React.createElement(component, props), elem[0]);
   });
 }
 
 // get prop name from prop (string or array)
-function getPropName(prop) {
+function getPropName(prop: any) {
   return Array.isArray(prop) ? prop[0] : prop;
 }
 
 // get prop name from prop (string or array)
-function getPropConfig(prop) {
+function getPropConfig(prop: any) {
   return Array.isArray(prop) ? prop[1] : {};
 }
 
 // get prop expression from prop (string or array)
-function getPropExpression(prop) {
+function getPropExpression(prop: any) {
   return Array.isArray(prop) ? prop[0] : prop;
 }
 
@@ -170,11 +172,12 @@ function findAttribute(attrs: string, propName: string): string {
   const index = Object.keys(attrs).find(attr => {
     return attr.toLowerCase() === propName.toLowerCase() || attr.toLowerCase() === kebabCase(propName);
   });
+  // @ts-ignore
   return attrs[index];
 }
 
 // get watch depth of prop (string or array)
-function getPropWatchDepth(defaultWatch, prop) {
+function getPropWatchDepth(defaultWatch: string, prop: string | any[]) {
   const customWatchDepth = Array.isArray(prop) && angular.isObject(prop[1]) && prop[1].watchDepth;
   return customWatchDepth || defaultWatch;
 }
@@ -197,11 +200,11 @@ function getPropWatchDepth(defaultWatch, prop) {
 //         }
 //     }));
 //
-const reactComponent = $injector => {
+const reactComponent = ($injector: any): any => {
   return {
     restrict: 'E',
     replace: true,
-    link: function(scope, elem, attrs) {
+    link: function(scope: any, elem: Element[], attrs: any) {
       const reactComponent = getReactComponent(attrs.name, $injector);
 
       const renderMyComponent = () => {
@@ -254,12 +257,12 @@ const reactComponent = $injector => {
 //
 //     <hello name="name"/>
 //
-const reactDirective = $injector => {
-  return (reactComponentName, props, conf, injectableProps) => {
+const reactDirective = ($injector: auto.IInjectorService) => {
+  return (reactComponentName: string, props: string[], conf: any, injectableProps: any) => {
     const directive = {
       restrict: 'E',
       replace: true,
-      link: function(scope, elem, attrs) {
+      link: function(scope: any, elem: Element[], attrs: any) {
         const reactComponent = getReactComponent(reactComponentName, $injector);
 
         // if props is not defined, fall back to use the React component's propTypes if present
@@ -267,8 +270,8 @@ const reactDirective = $injector => {
 
         // for each of the properties, get their scope value and set it to scope.props
         const renderMyComponent = () => {
-          let scopeProps = {};
-          const config = {};
+          let scopeProps: any = {};
+          const config: any = {};
 
           props.forEach(prop => {
             const propName = getPropName(prop);

+ 5 - 4
public/app/core/services/popover_srv.ts

@@ -1,10 +1,11 @@
 import _ from 'lodash';
 import coreModule from 'app/core/core_module';
+// @ts-ignore
 import Drop from 'tether-drop';
 
 /** @ngInject */
-function popoverSrv(this: any, $compile, $rootScope, $timeout) {
-  let openDrop = null;
+function popoverSrv(this: any, $compile: any, $rootScope: any, $timeout: any) {
+  let openDrop: any = null;
 
   this.close = () => {
     if (openDrop) {
@@ -12,14 +13,14 @@ function popoverSrv(this: any, $compile, $rootScope, $timeout) {
     }
   };
 
-  this.show = options => {
+  this.show = (options: any) => {
     if (openDrop) {
       openDrop.close();
       openDrop = null;
     }
 
     const scope = _.extend($rootScope.$new(true), options.model);
-    let drop;
+    let drop: any;
 
     const cleanUp = () => {
       setTimeout(() => {

+ 4 - 4
public/app/core/services/util_srv.ts

@@ -5,7 +5,7 @@ export class UtilSrv {
   modalScope: any;
 
   /** @ngInject */
-  constructor(private $rootScope, private $modal) {}
+  constructor(private $rootScope: any, private $modal: any) {}
 
   init() {
     appEvents.on('show-modal', this.showModal.bind(this), this.$rootScope);
@@ -19,7 +19,7 @@ export class UtilSrv {
     }
   }
 
-  showModal(options) {
+  showModal(options: any) {
     if (this.modalScope && this.modalScope.dismiss) {
       this.modalScope.dismiss();
     }
@@ -49,10 +49,10 @@ export class UtilSrv {
     });
   }
 
-  showConfirmModal(payload) {
+  showConfirmModal(payload: any) {
     const scope = this.$rootScope.$new();
 
-    scope.updateConfirmText = value => {
+    scope.updateConfirmText = (value: any) => {
       scope.confirmTextValid = payload.confirmText.toLowerCase() === value.toLowerCase();
     };
 

+ 1 - 1
public/app/core/specs/backend_srv.test.ts

@@ -4,7 +4,7 @@ import { ContextSrv } from '../services/context_srv';
 jest.mock('app/core/store');
 
 describe('backend_srv', () => {
-  const _httpBackend = options => {
+  const _httpBackend = (options: any) => {
     if (options.url === 'gateway-error') {
       return Promise.reject({ status: 502 });
     }

+ 3 - 2
public/app/core/specs/file_export.test.ts

@@ -1,5 +1,6 @@
 import * as fileExport from '../utils/file_export';
 import { beforeEach, expect } from 'test/lib/common';
+import { TableData } from '@grafana/data';
 
 describe('file_export', () => {
   const ctx: any = {};
@@ -74,7 +75,7 @@ describe('file_export', () => {
 
   describe('when exporting table data to csv', () => {
     it('should properly escape special characters and quote all string values', () => {
-      const inputTable = {
+      const inputTable: any = {
         columns: [
           { title: 'integer_value' },
           { text: 'string_value' },
@@ -116,7 +117,7 @@ describe('file_export', () => {
     });
 
     it('should decode HTML encoded characters', () => {
-      const inputTable = {
+      const inputTable: TableData = {
         columns: [{ text: 'string_value' }],
         rows: [
           ['&quot;&amp;&auml;'],

+ 1 - 1
public/app/core/specs/logs_model.test.ts

@@ -330,7 +330,7 @@ describe('LogsParsers', () => {
   });
 });
 
-const emptyLogsModel = {
+const emptyLogsModel: any = {
   hasUniqueLabels: false,
   rows: [],
   meta: [],

+ 5 - 4
public/app/core/specs/org_switcher.test.ts

@@ -1,4 +1,5 @@
 import { OrgSwitchCtrl } from '../components/org_switcher';
+// @ts-ignore
 import q from 'q';
 
 jest.mock('app/core/services/context_srv', () => ({
@@ -15,15 +16,15 @@ jest.mock('app/core/config', () => {
 
 describe('OrgSwitcher', () => {
   describe('when switching org', () => {
-    let expectedHref;
-    let expectedUsingUrl;
+    let expectedHref: string;
+    let expectedUsingUrl: string;
 
     beforeEach(() => {
       const backendSrvStub: any = {
-        get: url => {
+        get: (url: string) => {
           return q.resolve([]);
         },
-        post: url => {
+        post: (url: string) => {
           expectedUsingUrl = url;
           return q.resolve({});
         },

+ 5 - 5
public/app/core/specs/search.test.ts

@@ -51,7 +51,7 @@ describe('SearchCtrl', () => {
           items: [],
           selected: true,
           expanded: false,
-          toggle: i => (i.expanded = !i.expanded),
+          toggle: (i: any) => (i.expanded = !i.expanded),
         },
         {
           id: 0,
@@ -59,7 +59,7 @@ describe('SearchCtrl', () => {
           items: [{ id: 3, selected: false }, { id: 5, selected: false }],
           selected: false,
           expanded: true,
-          toggle: i => (i.expanded = !i.expanded),
+          toggle: (i: any) => (i.expanded = !i.expanded),
         },
       ];
     });
@@ -148,7 +148,7 @@ describe('SearchCtrl', () => {
           items: [{ id: 2, selected: false }, { id: 4, selected: false }],
           selected: true,
           expanded: false,
-          toggle: i => (i.expanded = !i.expanded),
+          toggle: (i: any) => (i.expanded = !i.expanded),
         },
         {
           id: 0,
@@ -156,7 +156,7 @@ describe('SearchCtrl', () => {
           items: [{ id: 3, selected: false }, { id: 5, selected: false }],
           selected: false,
           expanded: true,
-          toggle: i => (i.expanded = !i.expanded),
+          toggle: (i: any) => (i.expanded = !i.expanded),
         },
       ];
     });
@@ -252,7 +252,7 @@ describe('SearchCtrl', () => {
           items: [{ id: 3, selected: true }, { id: 5, selected: false }],
           selected: false,
           expanded: true,
-          toggle: i => (i.expanded = !i.expanded),
+          toggle: (i: any) => (i.expanded = !i.expanded),
         },
       ];
     });

+ 3 - 3
public/app/core/specs/search_results.test.ts

@@ -9,7 +9,7 @@ jest.mock('app/core/app_events', () => {
 });
 
 describe('SearchResultsCtrl', () => {
-  let ctrl;
+  let ctrl: any;
 
   describe('when checking an item that is not checked', () => {
     const item = { checked: false };
@@ -50,11 +50,11 @@ describe('SearchResultsCtrl', () => {
   });
 
   describe('when selecting a tag', () => {
-    let selectedTag = null;
+    let selectedTag: any = null;
 
     beforeEach(() => {
       ctrl = new SearchResultsCtrl({});
-      ctrl.onTagSelected = tag => (selectedTag = tag);
+      ctrl.onTagSelected = (tag: any) => (selectedTag = tag);
       ctrl.selectTag('tag-test');
     });
 

+ 6 - 3
public/app/core/specs/table_model.test.ts

@@ -1,13 +1,14 @@
 import TableModel, { mergeTablesIntoModel } from 'app/core/table_model';
 
 describe('when sorting table desc', () => {
-  let table;
+  let table: TableModel;
   const panel = {
     sort: { col: 0, desc: true },
   };
 
   beforeEach(() => {
     table = new TableModel();
+    // @ts-ignore
     table.columns = [{}, {}];
     table.rows = [[100, 12], [105, 10], [103, 11]];
     table.sort(panel.sort);
@@ -26,13 +27,14 @@ describe('when sorting table desc', () => {
 });
 
 describe('when sorting table asc', () => {
-  let table;
+  let table: TableModel;
   const panel = {
     sort: { col: 1, desc: false },
   };
 
   beforeEach(() => {
     table = new TableModel();
+    // @ts-ignore
     table.columns = [{}, {}];
     table.rows = [[100, 11], [105, 15], [103, 10]];
     table.sort(panel.sort);
@@ -46,11 +48,12 @@ describe('when sorting table asc', () => {
 });
 
 describe('when sorting with nulls', () => {
-  let table;
+  let table: TableModel;
   let values;
 
   beforeEach(() => {
     table = new TableModel();
+    // @ts-ignore
     table.columns = [{}, {}];
     table.rows = [[42, ''], [19, 'a'], [null, 'b'], [0, 'd'], [null, null], [2, 'c'], [0, null], [-8, '']];
   });

+ 6 - 6
public/app/core/specs/time_series.test.ts

@@ -2,9 +2,9 @@ import TimeSeries from 'app/core/time_series2';
 import { updateLegendValues } from 'app/core/time_series2';
 
 describe('TimeSeries', () => {
-  let points, series;
+  let points, series: any;
   const yAxisFormats = ['short', 'ms'];
-  let testData;
+  let testData: { alias?: string; datapoints: any };
 
   beforeEach(() => {
     testData = {
@@ -174,7 +174,7 @@ describe('TimeSeries', () => {
   });
 
   describe('can detect if series contains ms precision', () => {
-    let fakedata;
+    let fakedata: any;
 
     beforeEach(() => {
       fakedata = testData;
@@ -194,7 +194,7 @@ describe('TimeSeries', () => {
   });
 
   describe('series overrides', () => {
-    let series;
+    let series: any;
     beforeEach(() => {
       series = new TimeSeries(testData);
     });
@@ -313,7 +313,7 @@ describe('TimeSeries', () => {
   });
 
   describe('value formatter', () => {
-    let series;
+    let series: any;
     beforeEach(() => {
       series = new TimeSeries(testData);
     });
@@ -328,7 +328,7 @@ describe('TimeSeries', () => {
   });
 
   describe('legend decimals', () => {
-    let series, panel;
+    let series: any, panel: any;
     const height = 200;
     beforeEach(() => {
       testData = {

+ 5 - 4
public/app/core/specs/value_select_dropdown.test.ts

@@ -1,19 +1,20 @@
 import 'app/core/directives/value_select_dropdown';
 import { ValueSelectDropdownCtrl } from '../directives/value_select_dropdown';
+// @ts-ignore
 import q from 'q';
 
 describe('SelectDropdownCtrl', () => {
   const tagValuesMap: any = {};
 
   ValueSelectDropdownCtrl.prototype.onUpdated = jest.fn();
-  let ctrl;
+  let ctrl: ValueSelectDropdownCtrl;
 
   describe('Given simple variable', () => {
     beforeEach(() => {
       ctrl = new ValueSelectDropdownCtrl(q);
       ctrl.variable = {
         current: { text: 'hej', value: 'hej' },
-        getValuesForTag: key => {
+        getValuesForTag: (key: string) => {
           return Promise.resolve(tagValuesMap[key]);
         },
       };
@@ -36,7 +37,7 @@ describe('SelectDropdownCtrl', () => {
           { text: 'server-3', value: 'server-3' },
         ],
         tags: ['key1', 'key2', 'key3'],
-        getValuesForTag: key => {
+        getValuesForTag: (key: string) => {
           return Promise.resolve(tagValuesMap[key]);
         },
         multi: true,
@@ -143,7 +144,7 @@ describe('SelectDropdownCtrl', () => {
           { text: 'server-3', value: 'server-3' },
         ],
         tags: ['key1', 'key2', 'key3'],
-        getValuesForTag: key => {
+        getValuesForTag: (key: any) => {
           return Promise.resolve(tagValuesMap[key]);
         },
         multi: true,

+ 2 - 2
public/app/core/utils/connectWithReduxStore.tsx

@@ -2,10 +2,10 @@ import React from 'react';
 import { connect } from 'react-redux';
 import { store } from '../../store/store';
 
-export function connectWithStore(WrappedComponent, ...args) {
+export function connectWithStore(WrappedComponent: any, ...args: any[]) {
   const ConnectedWrappedComponent = (connect as any)(...args)(WrappedComponent);
 
-  return props => {
+  return (props: any) => {
     return <ConnectedWrappedComponent {...props} store={store} />;
   };
 }

+ 5 - 5
public/app/core/utils/css_loader.ts

@@ -3,13 +3,13 @@ const head = document.getElementsByTagName('head')[0];
 
 // get all link tags in the page
 const links = document.getElementsByTagName('link');
-const linkHrefs = [];
+const linkHrefs: string[] = [];
 for (let i = 0; i < links.length; i++) {
   linkHrefs.push(links[i].href);
 }
 
 const isWebkit = !!window.navigator.userAgent.match(/AppleWebKit\/([^ ;]*)/);
-const webkitLoadCheck = (link, callback) => {
+const webkitLoadCheck = (link: HTMLLinkElement, callback: Function) => {
   setTimeout(() => {
     for (let i = 0; i < document.styleSheets.length; i++) {
       const sheet = document.styleSheets[i];
@@ -23,14 +23,14 @@ const webkitLoadCheck = (link, callback) => {
 
 const noop = () => {};
 
-const loadCSS = url => {
+const loadCSS = (url: string) => {
   return new Promise((resolve, reject) => {
     const link = document.createElement('link');
     const timeout = setTimeout(() => {
       reject('Unable to load CSS');
     }, waitSeconds * 1000);
 
-    const _callback = error => {
+    const _callback = (error: any) => {
       clearTimeout(timeout);
       link.onload = link.onerror = noop;
       setTimeout(() => {
@@ -62,7 +62,7 @@ const loadCSS = url => {
   });
 };
 
-export function fetch(load): any {
+export function fetch(load: any): any {
   if (typeof window === 'undefined') {
     return '';
   }

+ 9 - 9
public/app/core/utils/dag.ts

@@ -2,7 +2,7 @@ export class Edge {
   inputNode: Node;
   outputNode: Node;
 
-  _linkTo(node, direction) {
+  _linkTo(node: Node, direction: number) {
     if (direction <= 0) {
       node.inputEdges.push(this);
     }
@@ -104,7 +104,7 @@ export class Node {
   }
 
   getOptimizedInputEdges(): Edge[] {
-    const toBeRemoved = [];
+    const toBeRemoved: any[] = [];
     this.inputEdges.forEach(e => {
       const inputEdgesNodes = e.inputNode.inputEdges.map(e => e.inputNode);
 
@@ -121,7 +121,7 @@ export class Node {
 }
 
 export class Graph {
-  nodes = {};
+  nodes: any = {};
 
   constructor() {}
 
@@ -132,7 +132,7 @@ export class Graph {
   }
 
   createNodes(names: string[]): Node[] {
-    const nodes = [];
+    const nodes: Node[] = [];
     names.forEach(name => {
       nodes.push(this.createNode(name));
     });
@@ -142,8 +142,8 @@ export class Graph {
   link(input: string | string[] | Node | Node[], output: string | string[] | Node | Node[]): Edge[] {
     let inputArr = [];
     let outputArr = [];
-    const inputNodes = [];
-    const outputNodes = [];
+    const inputNodes: Node[] = [];
+    const outputNodes: Node[] = [];
 
     if (input instanceof Array) {
       inputArr = input;
@@ -183,7 +183,7 @@ export class Graph {
       }
     }
 
-    const edges = [];
+    const edges: Edge[] = [];
     inputNodes.forEach(input => {
       outputNodes.forEach(output => {
         edges.push(this.createEdge().link(input, output));
@@ -204,11 +204,11 @@ export class Graph {
 export const printGraph = (g: Graph) => {
   Object.keys(g.nodes).forEach(name => {
     const n = g.nodes[name];
-    let outputEdges = n.outputEdges.map(e => e.outputNode.name).join(', ');
+    let outputEdges = n.outputEdges.map((e: Edge) => e.outputNode.name).join(', ');
     if (!outputEdges) {
       outputEdges = '<none>';
     }
-    let inputEdges = n.inputEdges.map(e => e.inputNode.name).join(', ');
+    let inputEdges = n.inputEdges.map((e: Edge) => e.inputNode.name).join(', ');
     if (!inputEdges) {
       inputEdges = '<none>';
     }

+ 4 - 4
public/app/core/utils/emitter.ts

@@ -7,11 +7,11 @@ export class Emitter {
     this.emitter = new EventEmitter();
   }
 
-  emit(name, data?) {
+  emit(name: string, data?: any) {
     this.emitter.emit(name, data);
   }
 
-  on(name, handler, scope?) {
+  on(name: string, handler: (payload?: any) => void, scope?: any) {
     this.emitter.on(name, handler);
 
     if (scope) {
@@ -22,11 +22,11 @@ export class Emitter {
     }
   }
 
-  removeAllListeners(evt?) {
+  removeAllListeners(evt?: string) {
     this.emitter.removeAllListeners(evt);
   }
 
-  off(name, handler) {
+  off(name: string, handler: (payload?: any) => void) {
     this.emitter.off(name, handler);
   }
 

+ 1 - 1
public/app/core/utils/errors.test.ts

@@ -1,7 +1,7 @@
 import { getMessageFromError } from 'app/core/utils/errors';
 
 describe('errors functions', () => {
-  let message;
+  let message: string;
 
   describe('when getMessageFromError gets an error string', () => {
     beforeEach(() => {

+ 2 - 2
public/app/core/utils/explore.test.ts

@@ -223,7 +223,7 @@ describe('instanceOfDataQueryError', () => {
 describe('hasRefId', () => {
   describe('when called with a null value', () => {
     it('then it should return null', () => {
-      const input = null;
+      const input: any = null;
       const result = getValueWithRefId(input);
 
       expect(result).toBeNull();
@@ -304,7 +304,7 @@ describe('getFirstQueryErrorWithoutRefId', () => {
 describe('getRefIds', () => {
   describe('when called with a null value', () => {
     it('then it should return empty array', () => {
-      const input = null;
+      const input: any = null;
       const result = getRefIds(input);
 
       expect(result).toEqual([]);

+ 4 - 4
public/app/core/utils/explore.ts

@@ -80,7 +80,7 @@ export async function getExploreUrl(
   // Mixed datasources need to choose only one datasource
   if (panelDatasource.meta.id === 'mixed' && panelTargets) {
     // Find first explore datasource among targets
-    let mixedExploreDatasource;
+    let mixedExploreDatasource: any;
     for (const t of panel.targets) {
       const datasource = await datasourceSrv.get(t.datasource);
       if (datasource && datasource.meta.explore) {
@@ -210,7 +210,7 @@ export const safeStringifyValue = (value: any, space?: number) => {
 
 export function parseUrlState(initial: string | undefined): ExploreUrlState {
   const parsed = safeParseJson(initial);
-  const errorResult = {
+  const errorResult: any = {
     datasource: null,
     queries: [],
     range: DEFAULT_RANGE,
@@ -323,7 +323,7 @@ const validKeys = ['refId', 'key', 'context'];
 export function hasNonEmptyQuery<TQuery extends DataQuery = any>(queries: TQuery[]): boolean {
   return (
     queries &&
-    queries.some(query => {
+    queries.some((query: any) => {
       const keys = Object.keys(query)
         .filter(key => validKeys.indexOf(key) === -1)
         .map(k => query[k])
@@ -386,7 +386,7 @@ export const getTimeRange = (timeZone: TimeZone, rawRange: RawTimeRange): TimeRa
   };
 };
 
-const parseRawTime = (value): TimeFragment => {
+const parseRawTime = (value: any): TimeFragment => {
   if (value === null) {
     return null;
   }

+ 18 - 13
public/app/core/utils/file_export.ts

@@ -1,7 +1,7 @@
 import { isBoolean, isNumber, sortedUniq, sortedIndexOf, unescape as htmlUnescaped } from 'lodash';
 import { saveAs } from 'file-saver';
 import { isNullOrUndefined } from 'util';
-import { dateTime, TimeZone } from '@grafana/data';
+import { dateTime, TimeZone, TableData } from '@grafana/data';
 
 const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ';
 const POINT_TIME_INDEX = 1;
@@ -18,6 +18,11 @@ interface SeriesListToCsvColumnsOptions {
   timezone: TimeZone;
 }
 
+type SeriesList = Array<{
+  datapoints: any;
+  alias: any;
+}>;
+
 const defaultOptions: SeriesListToCsvColumnsOptions = {
   dateTimeFormat: DEFAULT_DATETIME_FORMAT,
   excel: false,
@@ -50,11 +55,11 @@ function htmlDecoded(text: string) {
   return text.replace(regexp, htmlDecoded).replace(regexp, htmlDecoded);
 }
 
-function formatSpecialHeader(useExcelHeader) {
+function formatSpecialHeader(useExcelHeader: boolean) {
   return useExcelHeader ? `sep=${END_COLUMN}${END_ROW}` : '';
 }
 
-function formatRow(row, addEndRowDelimiter = true) {
+function formatRow(row: any[], addEndRowDelimiter = true) {
   let text = '';
   for (let i = 0; i < row.length; i += 1) {
     if (isBoolean(row[i]) || isNumber(row[i]) || isNullOrUndefined(row[i])) {
@@ -70,7 +75,7 @@ function formatRow(row, addEndRowDelimiter = true) {
   return addEndRowDelimiter ? text + END_ROW : text;
 }
 
-export function convertSeriesListToCsv(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
+export function convertSeriesListToCsv(seriesList: SeriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
   const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options };
   let text = formatSpecialHeader(excel) + formatRow(['Series', 'Time', 'Value']);
   for (let seriesIndex = 0; seriesIndex < seriesList.length; seriesIndex += 1) {
@@ -92,12 +97,12 @@ export function convertSeriesListToCsv(seriesList, options: Partial<SeriesListTo
   return text;
 }
 
-export function exportSeriesListToCsv(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
+export function exportSeriesListToCsv(seriesList: SeriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
   const text = convertSeriesListToCsv(seriesList, options);
   saveSaveBlob(text, EXPORT_FILENAME);
 }
 
-export function convertSeriesListToCsvColumns(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
+export function convertSeriesListToCsvColumns(seriesList: SeriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
   const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options };
   // add header
   let text =
@@ -138,7 +143,7 @@ export function convertSeriesListToCsvColumns(seriesList, options: Partial<Serie
  * Collect all unique timestamps from series list and use it to fill
  * missing points by null.
  */
-function mergeSeriesByTime(seriesList) {
+function mergeSeriesByTime(seriesList: SeriesList) {
   let timestamps = [];
   for (let i = 0; i < seriesList.length; i++) {
     const seriesPoints = seriesList[i].datapoints;
@@ -151,7 +156,7 @@ function mergeSeriesByTime(seriesList) {
   const result = [];
   for (let i = 0; i < seriesList.length; i++) {
     const seriesPoints = seriesList[i].datapoints;
-    const seriesTimestamps = seriesPoints.map(p => p[POINT_TIME_INDEX]);
+    const seriesTimestamps = seriesPoints.map((p: any) => p[POINT_TIME_INDEX]);
     const extendedDatapoints = [];
     for (let j = 0; j < timestamps.length; j++) {
       const timestamp = timestamps[j];
@@ -167,15 +172,15 @@ function mergeSeriesByTime(seriesList) {
   return result;
 }
 
-export function exportSeriesListToCsvColumns(seriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
+export function exportSeriesListToCsvColumns(seriesList: SeriesList, options: Partial<SeriesListToCsvColumnsOptions>) {
   const text = convertSeriesListToCsvColumns(seriesList, options);
   saveSaveBlob(text, EXPORT_FILENAME);
 }
 
-export function convertTableDataToCsv(table, excel = false) {
+export function convertTableDataToCsv(table: TableData, excel = false) {
   let text = formatSpecialHeader(excel);
   // add headline
-  text += formatRow(table.columns.map(val => val.title || val.text));
+  text += formatRow(table.columns.map((val: any) => val.title || val.text));
   // process data
   for (let i = 0; i < table.rows.length; i += 1) {
     text += formatRow(table.rows[i], i < table.rows.length - 1);
@@ -183,12 +188,12 @@ export function convertTableDataToCsv(table, excel = false) {
   return text;
 }
 
-export function exportTableDataToCsv(table, excel = false) {
+export function exportTableDataToCsv(table: TableData, excel = false) {
   const text = convertTableDataToCsv(table, excel);
   saveSaveBlob(text, EXPORT_FILENAME);
 }
 
-export function saveSaveBlob(payload, fname) {
+export function saveSaveBlob(payload: any, fname: string) {
   const blob = new Blob([payload], { type: 'text/csv;charset=utf-8;header=present;' });
   saveAs(blob, fname);
 }

+ 3 - 3
public/app/core/utils/flatten.ts

@@ -1,15 +1,15 @@
 // Copyright (c) 2014, Hugh Kennedy
 // Based on code from https://github.com/hughsk/flat/blob/master/index.js
 //
-export default function flatten(target, opts): any {
+export default function flatten(target: object, opts: { delimiter?: any; maxDepth?: any; safe?: any }): any {
   opts = opts || {};
 
   const delimiter = opts.delimiter || '.';
   let maxDepth = opts.maxDepth || 3;
   let currentDepth = 1;
-  const output = {};
+  const output: any = {};
 
-  function step(object, prev) {
+  function step(object: any, prev: string) {
     Object.keys(object).forEach(key => {
       const value = object[key];
       const isarray = opts.safe && Array.isArray(value);

+ 23 - 17
public/app/core/utils/kbn.ts

@@ -1,18 +1,18 @@
 import { has } from 'lodash';
 import { getValueFormat, getValueFormatterIndex, getValueFormats, deprecationWarning } from '@grafana/ui';
-import { stringToJsRegex } from '@grafana/data';
+import { stringToJsRegex, TimeRange } from '@grafana/data';
 
 const kbn: any = {};
 
 kbn.valueFormats = {};
 
-kbn.regexEscape = value => {
+kbn.regexEscape = (value: string) => {
   return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
 };
 
 ///// HELPER FUNCTIONS /////
 
-kbn.round_interval = interval => {
+kbn.round_interval = (interval: number) => {
   switch (true) {
     // 0.015s
     case interval < 15:
@@ -103,7 +103,7 @@ kbn.round_interval = interval => {
   }
 };
 
-kbn.secondsToHms = seconds => {
+kbn.secondsToHms = (seconds: number) => {
   const numyears = Math.floor(seconds / 31536000);
   if (numyears) {
     return numyears + 'y';
@@ -132,7 +132,7 @@ kbn.secondsToHms = seconds => {
   return 'less than a millisecond'; //'just now' //or other string you like;
 };
 
-kbn.secondsToHhmmss = seconds => {
+kbn.secondsToHhmmss = (seconds: number) => {
   const strings: string[] = [];
   const numhours = Math.floor(seconds / 3600);
   const numminutes = Math.floor((seconds % 3600) / 60);
@@ -143,11 +143,11 @@ kbn.secondsToHhmmss = seconds => {
   return strings.join(':');
 };
 
-kbn.to_percent = (nr, outof) => {
+kbn.to_percent = (nr: number, outof: number) => {
   return Math.floor((nr / outof) * 10000) / 100 + '%';
 };
 
-kbn.addslashes = str => {
+kbn.addslashes = (str: string) => {
   str = str.replace(/\\/g, '\\\\');
   str = str.replace(/\'/g, "\\'");
   str = str.replace(/\"/g, '\\"');
@@ -169,7 +169,7 @@ kbn.intervals_in_seconds = {
   ms: 0.001,
 };
 
-kbn.calculateInterval = (range, resolution, lowLimitInterval) => {
+kbn.calculateInterval = (range: TimeRange, resolution: number, lowLimitInterval: string[]) => {
   let lowLimitMs = 1; // 1 millisecond default low limit
   let intervalMs;
 
@@ -191,7 +191,7 @@ kbn.calculateInterval = (range, resolution, lowLimitInterval) => {
   };
 };
 
-kbn.describe_interval = str => {
+kbn.describe_interval = (str: string) => {
   const matches = str.match(kbn.interval_regex);
   if (!matches || !has(kbn.intervals_in_seconds, matches[2])) {
     throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"');
@@ -204,17 +204,17 @@ kbn.describe_interval = str => {
   }
 };
 
-kbn.interval_to_ms = str => {
+kbn.interval_to_ms = (str: string) => {
   const info = kbn.describe_interval(str);
   return info.sec * 1000 * info.count;
 };
 
-kbn.interval_to_seconds = str => {
+kbn.interval_to_seconds = (str: string) => {
   const info = kbn.describe_interval(str);
   return info.sec * info.count;
 };
 
-kbn.query_color_dot = (color, diameter) => {
+kbn.query_color_dot = (color: string, diameter: string) => {
   return (
     '<div class="icon-circle" style="' +
     ['display:inline-block', 'color:' + color, 'font-size:' + diameter + 'px'].join(';') +
@@ -222,7 +222,7 @@ kbn.query_color_dot = (color, diameter) => {
   );
 };
 
-kbn.slugifyForUrl = str => {
+kbn.slugifyForUrl = (str: string) => {
   return str
     .toLowerCase()
     .replace(/[^\w ]+/g, '')
@@ -230,12 +230,12 @@ kbn.slugifyForUrl = str => {
 };
 
 /** deprecated since 6.1, use grafana/data */
-kbn.stringToJsRegex = str => {
+kbn.stringToJsRegex = (str: string) => {
   deprecationWarning('kbn.ts', 'kbn.stringToJsRegex()', '@grafana/data');
   return stringToJsRegex(str);
 };
 
-kbn.toFixed = (value, decimals) => {
+kbn.toFixed = (value: number | null, decimals: number) => {
   if (value === null) {
     return '';
   }
@@ -261,7 +261,13 @@ kbn.toFixed = (value, decimals) => {
   return formatted;
 };
 
-kbn.toFixedScaled = (value, decimals, scaledDecimals, additionalDecimals, ext) => {
+kbn.toFixedScaled = (
+  value: number,
+  decimals: number,
+  scaledDecimals: number | null,
+  additionalDecimals: number,
+  ext: number
+) => {
   if (scaledDecimals === null) {
     return kbn.toFixed(value, decimals) + ext;
   } else {
@@ -269,7 +275,7 @@ kbn.toFixedScaled = (value, decimals, scaledDecimals, additionalDecimals, ext) =
   }
 };
 
-kbn.roundValue = (num, decimals) => {
+kbn.roundValue = (num: number, decimals: number) => {
   if (num === null) {
     return null;
   }

+ 1 - 1
public/app/core/utils/model_utils.ts

@@ -1,4 +1,4 @@
-export function assignModelProperties(target, source, defaults, removeDefaults?) {
+export function assignModelProperties(target: any, source: any, defaults: any, removeDefaults?: undefined) {
   for (const key in defaults) {
     if (!defaults.hasOwnProperty(key)) {
       continue;

+ 2 - 2
public/app/core/utils/outline.ts

@@ -5,7 +5,7 @@ function outlineFixer() {
   const styleElement = d.createElement('STYLE');
   const domEvents = 'addEventListener' in d;
 
-  const addEventListener = (type, callback) => {
+  const addEventListener = (type: string, callback: { (): void; (): void }) => {
     // Basic cross-browser event handling
     if (domEvents) {
       d.addEventListener(type, callback);
@@ -14,7 +14,7 @@ function outlineFixer() {
     }
   };
 
-  const setCss = cssText => {
+  const setCss = (cssText: string) => {
     // Handle setting of <style> element contents in IE8
     !!styleElement.styleSheet ? (styleElement.styleSheet.cssText = cssText) : (styleElement.innerHTML = cssText);
   };

+ 1 - 1
public/app/core/utils/reselect.ts

@@ -1,5 +1,5 @@
 import { memoize } from 'lodash';
 import { createSelectorCreator } from 'reselect';
 
-const hashFn = (...args) => args.reduce((acc, val) => acc + '-' + JSON.stringify(val), '');
+const hashFn = (...args: any[]) => args.reduce((acc, val) => acc + '-' + JSON.stringify(val), '');
 export const createLodashMemoizedSelector = createSelectorCreator(memoize as any, hashFn);

+ 2 - 1
public/app/core/utils/scrollbar.ts

@@ -1,6 +1,6 @@
 // Slightly modified, but without dependancies:
 // https://raw.githubusercontent.com/malte-wessel/react-custom-scrollbars/master/src/utils/getScrollbarWidth.js
-let scrollbarWidth = null;
+let scrollbarWidth: number | null = null;
 
 export default function getScrollbarWidth() {
   if (scrollbarWidth !== null) {
@@ -19,6 +19,7 @@ export default function getScrollbarWidth() {
     };
 
     Object.keys(newStyles).map(style => {
+      // @ts-ignore
       div.style[style] = newStyles[style];
     });
 

+ 2 - 2
public/app/core/utils/sort_by_keys.ts

@@ -1,12 +1,12 @@
 import _ from 'lodash';
 
-export default function sortByKeys(input) {
+export default function sortByKeys(input: any): any {
   if (_.isArray(input)) {
     return input.map(sortByKeys);
   }
 
   if (_.isPlainObject(input)) {
-    const sortedObject = {};
+    const sortedObject: any = {};
     for (const key of _.keys(input).sort()) {
       sortedObject[key] = sortByKeys(input[key]);
     }

+ 1 - 1
public/app/core/utils/tags.ts

@@ -73,7 +73,7 @@ export function getTagColorsFromName(name: string): { color: string; borderColor
   return { color, borderColor };
 }
 
-function djb2(str) {
+function djb2(str: string) {
   let hash = 5381;
   for (let i = 0; i < str.length; i++) {
     hash = (hash << 5) + hash + str.charCodeAt(i); /* hash * 33 + c */

+ 10 - 3
public/app/core/utils/text.ts

@@ -5,8 +5,14 @@ import xss from 'xss';
  * Adapt findMatchesInText for react-highlight-words findChunks handler.
  * See https://github.com/bvaughn/react-highlight-words#props
  */
-export function findHighlightChunksInText({ searchWords, textToHighlight }) {
-  return searchWords.reduce((acc, term) => [...acc, ...findMatchesInText(textToHighlight, term)], []);
+export function findHighlightChunksInText({
+  searchWords,
+  textToHighlight,
+}: {
+  searchWords: string[];
+  textToHighlight: string;
+}) {
+  return searchWords.reduce((acc: any, term: string) => [...acc, ...findMatchesInText(textToHighlight, term)], []);
 }
 
 const cleanNeedle = (needle: string): string => {
@@ -21,7 +27,7 @@ export function findMatchesInText(haystack: string, needle: string): TextMatch[]
   if (!haystack || !needle) {
     return [];
   }
-  const matches = [];
+  const matches: TextMatch[] = [];
   const { cleaned, flags } = parseFlags(cleanNeedle(needle));
   let regexp: RegExp;
   try {
@@ -74,6 +80,7 @@ export function parseFlags(text: string): { cleaned: string; flags: string } {
 }
 
 const XSSWL = Object.keys(xss.whiteList).reduce((acc, element) => {
+  // @ts-ignore
   acc[element] = xss.whiteList[element].concat(['class', 'style']);
   return acc;
 }, {});

+ 5 - 5
public/app/core/utils/ticks.ts

@@ -26,7 +26,7 @@ export function tickStep(start: number, stop: number, count: number): number {
   return stop < start ? -step1 : step1;
 }
 
-export function getScaledDecimals(decimals, tickSize) {
+export function getScaledDecimals(decimals: number, tickSize: number) {
   return decimals - Math.floor(Math.log(tickSize) / Math.LN10);
 }
 
@@ -71,7 +71,7 @@ export function getFlotTickSize(min: number, max: number, noTicks: number, tickD
  * Calculate axis range (min and max).
  * Implementation from Flot.
  */
-export function getFlotRange(panelMin, panelMax, datamin, datamax) {
+export function getFlotRange(panelMin: any, panelMax: any, datamin: number, datamax: number) {
   const autoscaleMargin = 0.02;
 
   let min = +(panelMin != null ? panelMin : datamin);
@@ -119,7 +119,7 @@ export function getFlotRange(panelMin, panelMax, datamin, datamax) {
  * Calculate tick decimals.
  * Implementation from Flot.
  */
-export function getFlotTickDecimals(datamin, datamax, axis, height) {
+export function getFlotTickDecimals(datamin: number, datamax: number, axis: { min: any; max: any }, height: number) {
   const { min, max } = getFlotRange(axis.min, axis.max, datamin, datamax);
   const noTicks = 0.3 * Math.sqrt(height);
   const delta = (max - min) / noTicks;
@@ -157,7 +157,7 @@ export function getFlotTickDecimals(datamin, datamax, axis, height) {
  * @param min Time from (in milliseconds)
  * @param max Time to (in milliseconds)
  */
-export function grafanaTimeFormat(ticks, min, max) {
+export function grafanaTimeFormat(ticks: number, min: number, max: number) {
   if (min && max && ticks) {
     const range = max - min;
     const secPerTick = range / ticks / 1000;
@@ -185,7 +185,7 @@ export function grafanaTimeFormat(ticks, min, max) {
 /**
  * Logarithm of value for arbitrary base.
  */
-export function logp(value, base) {
+export function logp(value: number, base: number) {
   return Math.log(value) / Math.log(base);
 }
 

+ 2 - 2
public/app/core/utils/url.ts

@@ -22,7 +22,7 @@ export function encodeURIComponentAsAngularJS(val: string, pctEncodeSpaces?: boo
 }
 
 export function toUrlParams(a: any) {
-  const s = [];
+  const s: any[] = [];
   const rbracket = /\[\]$/;
 
   const isArray = (obj: any) => {
@@ -72,7 +72,7 @@ export function toUrlParams(a: any) {
   return buildParams('', a).join('&');
 }
 
-export function appendQueryToUrl(url, stringToAppend) {
+export function appendQueryToUrl(url: string, stringToAppend: string) {
   if (stringToAppend !== undefined && stringToAppend !== null && stringToAppend !== '') {
     const pos = url.indexOf('?');
     if (pos !== -1) {

+ 1 - 1
public/app/features/admin/AdminEditUserCtrl.ts

@@ -175,7 +175,7 @@ export default class AdminEditUserCtrl {
       });
     };
 
-    $scope.disableUser = event => {
+    $scope.disableUser = (event: any) => {
       const user = $scope.user;
 
       // External user can not be disabled

+ 1 - 1
public/app/features/alerting/AlertTabCtrl.ts

@@ -167,7 +167,7 @@ export class AlertTabCtrl {
     this.newAlertRuleTag.value = '';
   }
 
-  removeAlertRuleTag(tagName) {
+  removeAlertRuleTag(tagName: string) {
     delete this.alert.alertRuleTags[tagName];
   }
 

+ 1 - 1
public/app/features/alerting/TestRuleResult.tsx

@@ -40,7 +40,7 @@ export class TestRuleResult extends PureComponent<Props, State> {
     this.setState({ isLoading: false, testRuleResponse });
   }
 
-  setFormattedJson = formattedJson => {
+  setFormattedJson = (formattedJson: any) => {
     this.formattedJson = formattedJson;
   };
 

+ 10 - 3
public/app/features/annotations/annotation_tooltip.ts

@@ -2,10 +2,17 @@ import _ from 'lodash';
 import $ from 'jquery';
 import coreModule from 'app/core/core_module';
 import alertDef from '../alerting/state/alertDef';
+import { DashboardSrv } from '../dashboard/services/DashboardSrv';
+import { ContextSrv } from 'app/core/services/context_srv';
 
 /** @ngInject */
-export function annotationTooltipDirective($sanitize, dashboardSrv, contextSrv, $compile) {
-  function sanitizeString(str) {
+export function annotationTooltipDirective(
+  $sanitize: any,
+  dashboardSrv: DashboardSrv,
+  contextSrv: ContextSrv,
+  $compile: any
+) {
+  function sanitizeString(str: string) {
     try {
       return $sanitize(str);
     } catch (err) {
@@ -20,7 +27,7 @@ export function annotationTooltipDirective($sanitize, dashboardSrv, contextSrv,
       event: '=',
       onEdit: '&',
     },
-    link: (scope, element) => {
+    link: (scope: any, element: JQuery) => {
       const event = scope.event;
       let title = event.title;
       let text = event.text;

+ 4 - 3
public/app/features/annotations/annotations_srv.ts

@@ -14,6 +14,7 @@ import { DashboardModel } from '../dashboard/state/DashboardModel';
 import DatasourceSrv from '../plugins/datasource_srv';
 import { BackendSrv } from 'app/core/services/backend_srv';
 import { TimeSrv } from '../dashboard/services/TimeSrv';
+import { AnnotationEvent } from '@grafana/data';
 
 export class AnnotationsSrv {
   globalAnnotationsPromise: any;
@@ -150,17 +151,17 @@ export class AnnotationsSrv {
     return this.globalAnnotationsPromise;
   }
 
-  saveAnnotationEvent(annotation: any) {
+  saveAnnotationEvent(annotation: AnnotationEvent) {
     this.globalAnnotationsPromise = null;
     return this.backendSrv.post('/api/annotations', annotation);
   }
 
-  updateAnnotationEvent(annotation: { id: any }) {
+  updateAnnotationEvent(annotation: AnnotationEvent) {
     this.globalAnnotationsPromise = null;
     return this.backendSrv.put(`/api/annotations/${annotation.id}`, annotation);
   }
 
-  deleteAnnotationEvent(annotation: { id: any; isRegion: any; regionId: any }) {
+  deleteAnnotationEvent(annotation: AnnotationEvent) {
     this.globalAnnotationsPromise = null;
     let deleteUrl = `/api/annotations/${annotation.id}`;
     if (annotation.isRegion) {

+ 8 - 9
public/app/features/annotations/editor_ctrl.ts

@@ -3,6 +3,7 @@ import _ from 'lodash';
 import $ from 'jquery';
 import coreModule from 'app/core/core_module';
 import { DashboardModel } from 'app/features/dashboard/state';
+import DatasourceSrv from '../plugins/datasource_srv';
 
 export class AnnotationsEditorCtrl {
   mode: any;
@@ -25,7 +26,7 @@ export class AnnotationsEditorCtrl {
   showOptions: any = [{ text: 'All Panels', value: 0 }, { text: 'Specific Panels', value: 1 }];
 
   /** @ngInject */
-  constructor($scope, private datasourceSrv) {
+  constructor($scope: any, private datasourceSrv: DatasourceSrv) {
     $scope.ctrl = this;
 
     this.dashboard = $scope.dashboard;
@@ -37,13 +38,11 @@ export class AnnotationsEditorCtrl {
     this.onColorChange = this.onColorChange.bind(this);
   }
 
-  datasourceChanged() {
-    return this.datasourceSrv.get(this.currentAnnotation.datasource).then(ds => {
-      this.currentDatasource = ds;
-    });
+  async datasourceChanged() {
+    return (this.currentDatasource = await this.datasourceSrv.get(this.currentAnnotation.datasource));
   }
 
-  edit(annotation) {
+  edit(annotation: any) {
     this.currentAnnotation = annotation;
     this.currentAnnotation.showIn = this.currentAnnotation.showIn || 0;
     this.currentIsNew = false;
@@ -73,7 +72,7 @@ export class AnnotationsEditorCtrl {
     this.mode = 'list';
   }
 
-  move(index, dir) {
+  move(index: number, dir: number) {
     // @ts-ignore
     _.move(this.annotations, index, index + dir);
   }
@@ -85,13 +84,13 @@ export class AnnotationsEditorCtrl {
     this.dashboard.updateSubmenuVisibility();
   }
 
-  removeAnnotation(annotation) {
+  removeAnnotation(annotation: any) {
     const index = _.indexOf(this.annotations, annotation);
     this.annotations.splice(index, 1);
     this.dashboard.updateSubmenuVisibility();
   }
 
-  onColorChange(newColor) {
+  onColorChange(newColor: string) {
     this.currentAnnotation.iconColor = newColor;
   }
 }

+ 3 - 2
public/app/features/annotations/event_editor.ts

@@ -3,6 +3,7 @@ import { coreModule } from 'app/core/core';
 import { MetricsPanelCtrl } from 'app/plugins/sdk';
 import { AnnotationEvent } from '@grafana/data';
 import { dateTime } from '@grafana/data';
+import { AnnotationsSrv } from './all';
 
 export class EventEditorCtrl {
   panelCtrl: MetricsPanelCtrl;
@@ -13,7 +14,7 @@ export class EventEditorCtrl {
   timeFormated: string;
 
   /** @ngInject */
-  constructor(private annotationsSrv) {
+  constructor(private annotationsSrv: AnnotationsSrv) {
     this.event.panelId = this.panelCtrl.panel.id;
     this.event.dashboardId = this.panelCtrl.dashboard.id;
 
@@ -83,7 +84,7 @@ export class EventEditorCtrl {
   }
 }
 
-function tryEpochToMoment(timestamp) {
+function tryEpochToMoment(timestamp: any) {
   if (timestamp && _.isNumber(timestamp)) {
     const epoch = Number(timestamp);
     return dateTime(epoch);

+ 6 - 6
public/app/features/annotations/event_manager.ts

@@ -28,7 +28,7 @@ export class EventManager {
     this.editorOpen = true;
   }
 
-  updateTime(range) {
+  updateTime(range: { from: any; to: any }) {
     if (!this.event) {
       this.event = {};
       this.event.dashboardId = this.panelCtrl.dashboard.id;
@@ -47,17 +47,17 @@ export class EventManager {
     this.panelCtrl.render();
   }
 
-  editEvent(event, elem?) {
+  editEvent(event: AnnotationEvent, elem?: any) {
     this.event = event;
     this.panelCtrl.render();
   }
 
-  addFlotEvents(annotations, flotOptions) {
+  addFlotEvents(annotations: any, flotOptions: any) {
     if (!this.event && annotations.length === 0) {
       return;
     }
 
-    const types = {
+    const types: any = {
       $__alerting: {
         color: ALERTING_COLOR,
         position: 'BOTTOM',
@@ -149,11 +149,11 @@ export class EventManager {
   }
 }
 
-function getRegions(events) {
+function getRegions(events: AnnotationEvent[]) {
   return _.filter(events, 'isRegion');
 }
 
-function addRegionMarking(regions, flotOptions) {
+function addRegionMarking(regions: any[], flotOptions: { grid: { markings: any } }) {
   const markings = flotOptions.grid.markings;
   const defaultColor = DEFAULT_ANNOTATION_COLOR;
   let fillColor;

+ 5 - 5
public/app/features/annotations/events_processing.ts

@@ -6,14 +6,14 @@ import _ from 'lodash';
  * @param annotations
  * @param options
  */
-export function makeRegions(annotations, options) {
+export function makeRegions(annotations: any[], options: { range: any }) {
   const [regionEvents, singleEvents] = _.partition(annotations, 'regionId');
   const regions = getRegions(regionEvents, options.range);
   annotations = _.concat(regions, singleEvents);
   return annotations;
 }
 
-function getRegions(events, range) {
+function getRegions(events: string | any[], range: { to: { valueOf: () => number }; from: { valueOf: () => number } }) {
   const regionEvents = _.filter(events, event => {
     return event.regionId;
   });
@@ -49,11 +49,11 @@ function getRegions(events, range) {
   return regions;
 }
 
-function isStartOfRegion(event): boolean {
+function isStartOfRegion(event: { id: any; regionId: any }): boolean {
   return event.id && event.id === event.regionId;
 }
 
-export function dedupAnnotations(annotations) {
+export function dedupAnnotations(annotations: any) {
   let dedup = [];
 
   // Split events by annotationId property existence
@@ -75,6 +75,6 @@ export function dedupAnnotations(annotations) {
   return dedup;
 }
 
-function isPanelAlert(event) {
+function isPanelAlert(event: { eventType: string }) {
   return event.eventType === 'panel-alert';
 }

+ 1 - 1
public/app/features/annotations/specs/annotations_srv.test.ts

@@ -21,7 +21,7 @@ describe('AnnotationsSrv', () => {
 
     const time = 1507039543000;
     const annotations = [{ id: 1, panelId: 1, text: 'text', time: time }];
-    let translatedAnnotations;
+    let translatedAnnotations: any;
 
     beforeEach(() => {
       translatedAnnotations = annotationsSrv.translateQueryResult(annotationSource, annotations);

+ 6 - 6
public/app/features/api-keys/ApiKeysPage.tsx

@@ -74,7 +74,7 @@ const tooltipText =
   'The api key life duration. For example 1d if your key is going to last for one day. All the supported units are: s,m,h,d,w,M,y';
 
 export class ApiKeysPage extends PureComponent<Props, any> {
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     this.state = { isAdding: false, newApiKey: initialApiKeyState };
   }
@@ -99,7 +99,7 @@ export class ApiKeysPage extends PureComponent<Props, any> {
     this.setState({ isAdding: !this.state.isAdding });
   };
 
-  onAddApiKey = async evt => {
+  onAddApiKey = async (evt: any) => {
     evt.preventDefault();
 
     const openModal = (apiKey: string) => {
@@ -124,10 +124,10 @@ export class ApiKeysPage extends PureComponent<Props, any> {
     });
   };
 
-  onApiKeyStateUpdate = (evt, prop: string) => {
+  onApiKeyStateUpdate = (evt: any, prop: string) => {
     const value = evt.currentTarget.value;
     this.setState((prevState: State) => {
-      const newApiKey = {
+      const newApiKey: any = {
         ...prevState.newApiKey,
       };
       newApiKey[prop] = value;
@@ -163,7 +163,7 @@ export class ApiKeysPage extends PureComponent<Props, any> {
     );
   }
 
-  formatDate(date, format?) {
+  formatDate(date: any, format?: string) {
     if (!date) {
       return 'No expiration date';
     }
@@ -304,7 +304,7 @@ export class ApiKeysPage extends PureComponent<Props, any> {
   }
 }
 
-function mapStateToProps(state) {
+function mapStateToProps(state: any) {
   return {
     navModel: getNavModel(state.navIndex, 'apikeys'),
     apiKeys: getApiKeys(state.apiKeys),

+ 15 - 7
public/app/features/dashboard/components/AdHocFilters/AdHocFiltersCtrl.ts

@@ -1,7 +1,9 @@
 import _ from 'lodash';
-import angular from 'angular';
+import angular, { IQService } from 'angular';
 import coreModule from 'app/core/core_module';
 import { DashboardModel } from 'app/features/dashboard/state';
+import DatasourceSrv from 'app/features/plugins/datasource_srv';
+import { VariableSrv } from 'app/features/templating/all';
 
 export class AdHocFiltersCtrl {
   segments: any;
@@ -10,7 +12,13 @@ export class AdHocFiltersCtrl {
   removeTagFilterSegment: any;
 
   /** @ngInject */
-  constructor(private uiSegmentSrv, private datasourceSrv, private $q, private variableSrv, $scope) {
+  constructor(
+    private uiSegmentSrv: any,
+    private datasourceSrv: DatasourceSrv,
+    private $q: IQService,
+    private variableSrv: VariableSrv,
+    $scope: any
+  ) {
     this.removeTagFilterSegment = uiSegmentSrv.newSegment({
       fake: true,
       value: '-- remove filter --',
@@ -40,7 +48,7 @@ export class AdHocFiltersCtrl {
     this.segments.push(this.uiSegmentSrv.newPlusButton());
   }
 
-  getOptions(segment, index) {
+  getOptions(segment: { type: string }, index: number) {
     if (segment.type === 'operator') {
       return this.$q.when(this.uiSegmentSrv.newOperators(['=', '!=', '<', '>', '=~', '!~']));
     }
@@ -60,7 +68,7 @@ export class AdHocFiltersCtrl {
         promise = ds.getTagValues ? ds.getTagValues(options) : Promise.resolve([]);
       }
 
-      return promise.then(results => {
+      return promise.then((results: any) => {
         results = _.map(results, segment => {
           return this.uiSegmentSrv.newSegment({ value: segment.text });
         });
@@ -74,7 +82,7 @@ export class AdHocFiltersCtrl {
     });
   }
 
-  segmentChanged(segment, index) {
+  segmentChanged(segment: { value: any; type: string; cssClass: string }, index: number) {
     this.segments[index] = segment;
 
     // handle remove tag condition
@@ -108,11 +116,11 @@ export class AdHocFiltersCtrl {
   }
 
   updateVariableModel() {
-    const filters = [];
+    const filters: any[] = [];
     let filterIndex = -1;
     let hasFakes = false;
 
-    this.segments.forEach(segment => {
+    this.segments.forEach((segment: any) => {
       if (segment.type === 'value' && segment.fake) {
         hasFakes = true;
         return;

+ 6 - 4
public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx

@@ -16,6 +16,8 @@ import { DashboardModel } from '../../state';
 import { LS_PANEL_COPY_KEY } from 'app/core/constants';
 import { LocationUpdate } from '@grafana/runtime';
 
+export type PanelPluginInfo = { id: any; defaults: { gridPos: { w: any; h: any }; title: any } };
+
 export interface Props {
   panel: PanelModel;
   dashboard: DashboardModel;
@@ -26,7 +28,7 @@ export interface State {
 }
 
 export class AddPanelWidget extends React.Component<Props, State> {
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     this.handleCloseAddPanel = this.handleCloseAddPanel.bind(this);
 
@@ -58,7 +60,7 @@ export class AddPanelWidget extends React.Component<Props, State> {
     return _.sortBy(copiedPanels, 'sort');
   }
 
-  handleCloseAddPanel(evt) {
+  handleCloseAddPanel(evt: any) {
     evt.preventDefault();
     this.props.dashboard.removePanel(this.props.panel);
   }
@@ -93,7 +95,7 @@ export class AddPanelWidget extends React.Component<Props, State> {
     reduxStore.dispatch(updateLocation(location));
   };
 
-  onPasteCopiedPanel = panelPluginInfo => {
+  onPasteCopiedPanel = (panelPluginInfo: PanelPluginInfo) => {
     const dashboard = this.props.dashboard;
     const { gridPos } = this.props.panel;
 
@@ -132,7 +134,7 @@ export class AddPanelWidget extends React.Component<Props, State> {
     dashboard.removePanel(this.props.panel);
   };
 
-  renderOptionLink = (icon: string, text: string, onClick) => {
+  renderOptionLink = (icon: string, text: string, onClick: any) => {
     return (
       <div>
         <a

+ 8 - 1
public/app/features/dashboard/components/DashExportModal/DashExportCtrl.ts

@@ -3,6 +3,8 @@ import { saveAs } from 'file-saver';
 
 import coreModule from 'app/core/core_module';
 import { DashboardExporter } from './DashboardExporter';
+import { DashboardSrv } from '../../services/DashboardSrv';
+import DatasourceSrv from 'app/features/plugins/datasource_srv';
 
 export class DashExportCtrl {
   dash: any;
@@ -11,7 +13,12 @@ export class DashExportCtrl {
   shareExternally: boolean;
 
   /** @ngInject */
-  constructor(private dashboardSrv, datasourceSrv, private $scope, private $rootScope) {
+  constructor(
+    private dashboardSrv: DashboardSrv,
+    datasourceSrv: DatasourceSrv,
+    private $scope: any,
+    private $rootScope: any
+  ) {
     this.exporter = new DashboardExporter(datasourceSrv);
 
     this.dash = this.dashboardSrv.getCurrent();

+ 21 - 8
public/app/features/dashboard/components/DashLinks/DashLinksContainerCtrl.ts

@@ -1,6 +1,11 @@
-import angular from 'angular';
+import angular, { IQService } from 'angular';
 import _ from 'lodash';
 import { iconMap } from './DashLinksEditorCtrl';
+import { LinkSrv } from 'app/features/panel/panellinks/link_srv';
+import { BackendSrv } from 'app/core/services/backend_srv';
+import { DashboardSrv } from '../../services/DashboardSrv';
+
+export type DashboardLink = { tags: any; target: string; keepTime: any; includeVars: any };
 
 function dashLinksContainer() {
   return {
@@ -16,10 +21,10 @@ function dashLinksContainer() {
 }
 
 /** @ngInject */
-function dashLink($compile, $sanitize, linkSrv) {
+function dashLink($compile: any, $sanitize: any, linkSrv: LinkSrv) {
   return {
     restrict: 'E',
-    link: (scope, elem) => {
+    link: (scope: any, elem: JQuery) => {
       const link = scope.link;
       const dashboard = scope.dashboard;
 
@@ -86,10 +91,17 @@ function dashLink($compile, $sanitize, linkSrv) {
 
 export class DashLinksContainerCtrl {
   /** @ngInject */
-  constructor($scope, $rootScope, $q, backendSrv, dashboardSrv, linkSrv) {
+  constructor(
+    $scope: any,
+    $rootScope: any,
+    $q: IQService,
+    backendSrv: BackendSrv,
+    dashboardSrv: DashboardSrv,
+    linkSrv: LinkSrv
+  ) {
     const currentDashId = dashboardSrv.getCurrent().id;
 
-    function buildLinks(linkDef) {
+    function buildLinks(linkDef: any) {
       if (linkDef.type === 'dashboards') {
         if (!linkDef.tags) {
           console.log('Dashboard link missing tag');
@@ -118,6 +130,7 @@ export class DashLinksContainerCtrl {
           {
             url: linkDef.url,
             title: linkDef.title,
+            // @ts-ignore
             icon: iconMap[linkDef.icon],
             tooltip: linkDef.tooltip,
             target: linkDef.targetBlank ? '_blank' : '_self',
@@ -138,7 +151,7 @@ export class DashLinksContainerCtrl {
       });
     }
 
-    $scope.searchDashboards = (link, limit) => {
+    $scope.searchDashboards = (link: DashboardLink, limit: any) => {
       return backendSrv.search({ tag: link.tags, limit: limit }).then(results => {
         return _.reduce(
           results,
@@ -161,8 +174,8 @@ export class DashLinksContainerCtrl {
       });
     };
 
-    $scope.fillDropdown = link => {
-      $scope.searchDashboards(link, 100).then(results => {
+    $scope.fillDropdown = (link: { searchHits: any }) => {
+      $scope.searchDashboards(link, 100).then((results: any) => {
         _.each(results, hit => {
           hit.url = linkSrv.getLinkUrl(hit);
         });

+ 4 - 4
public/app/features/dashboard/components/DashLinks/DashLinksEditorCtrl.ts

@@ -19,7 +19,7 @@ export class DashLinksEditorCtrl {
   link: any;
 
   /** @ngInject */
-  constructor($scope, $rootScope) {
+  constructor($scope: any, $rootScope: any) {
     this.iconMap = iconMap;
     this.dashboard.links = this.dashboard.links || [];
     this.mode = 'list';
@@ -44,7 +44,7 @@ export class DashLinksEditorCtrl {
     this.dashboard.updateSubmenuVisibility();
   }
 
-  editLink(link) {
+  editLink(link: any) {
     this.link = link;
     this.mode = 'edit';
     console.log(this.link);
@@ -54,12 +54,12 @@ export class DashLinksEditorCtrl {
     this.backToList();
   }
 
-  moveLink(index, dir) {
+  moveLink(index: string | number, dir: string | number) {
     // @ts-ignore
     _.move(this.dashboard.links, index, index + dir);
   }
 
-  deleteLink(index) {
+  deleteLink(index: number) {
     this.dashboard.links.splice(index, 1);
     this.dashboard.updateSubmenuVisibility();
   }

+ 1 - 1
public/app/features/dashboard/components/DashNav/DashNav.tsx

@@ -87,7 +87,7 @@ export class DashNav extends PureComponent<Props> {
     const { dashboard, $injector } = this.props;
     const dashboardSrv = $injector.get('dashboardSrv');
 
-    dashboardSrv.starDashboard(dashboard.id, dashboard.meta.isStarred).then(newState => {
+    dashboardSrv.starDashboard(dashboard.id, dashboard.meta.isStarred).then((newState: any) => {
       dashboard.meta.isStarred = newState;
       this.forceUpdate();
     });

+ 1 - 1
public/app/features/dashboard/components/DashboardPermissions/DashboardPermissions.tsx

@@ -29,7 +29,7 @@ export interface State {
 }
 
 export class DashboardPermissions extends PureComponent<Props, State> {
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
 
     this.state = {

+ 1 - 1
public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx

@@ -4,7 +4,7 @@ import { DashboardRow } from './DashboardRow';
 import { PanelModel } from '../../state/PanelModel';
 
 describe('DashboardRow', () => {
-  let wrapper, panel, dashboardMock;
+  let wrapper: any, panel: PanelModel, dashboardMock: any;
 
   beforeEach(() => {
     dashboardMock = {

+ 2 - 2
public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx

@@ -11,7 +11,7 @@ export interface DashboardRowProps {
 }
 
 export class DashboardRow extends React.Component<DashboardRowProps, any> {
-  constructor(props) {
+  constructor(props: DashboardRowProps) {
     super(props);
 
     this.state = {
@@ -32,7 +32,7 @@ export class DashboardRow extends React.Component<DashboardRowProps, any> {
   onToggle = () => {
     this.props.dashboard.toggleRow(this.props.panel);
 
-    this.setState(prevState => {
+    this.setState((prevState: any) => {
       return { collapsed: !prevState.collapsed };
     });
   };

+ 1 - 1
public/app/features/dashboard/components/ExportDataModal/ExportDataModalCtrl.ts

@@ -4,7 +4,7 @@ import appEvents from 'app/core/app_events';
 import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
 
 export class ExportDataModalCtrl {
-  private data: any[];
+  private data: any;
   private panel: string;
   asRows = true;
   dateTimeFormat = 'YYYY-MM-DDTHH:mm:ssZ';

+ 2 - 2
public/app/features/dashboard/state/DashboardModel.ts

@@ -798,11 +798,11 @@ export class DashboardModel {
     return rowPanels;
   }
 
-  on(eventName: string, callback: Function) {
+  on(eventName: string, callback: (payload?: any) => void) {
     this.events.on(eventName, callback);
   }
 
-  off(eventName: string, callback?: Function) {
+  off(eventName: string, callback?: (payload?: any) => void) {
     this.events.off(eventName, callback);
   }
 

+ 1 - 1
scripts/ci-frontend-metrics.sh

@@ -3,7 +3,7 @@
 echo -e "Collecting code stats (typescript errors & more)"
 
 
-ERROR_COUNT_LIMIT=800
+ERROR_COUNT_LIMIT=0
 DIRECTIVES_LIMIT=172
 CONTROLLERS_LIMIT=139
 

+ 1 - 1
tsconfig.json

@@ -22,7 +22,7 @@
     "noImplicitReturns": true,
     "noImplicitThis": true,
     "noImplicitUseStrict": false,
-    "noImplicitAny": false,
+    "noImplicitAny": true,
     "downlevelIteration": true,
     "noUnusedLocals": true,
     "baseUrl": "public",

+ 6 - 1
yarn.lock

@@ -2974,7 +2974,7 @@
     "@types/express-serve-static-core" "*"
     "@types/serve-static" "*"
 
-"@types/file-saver@^2.0.1":
+"@types/file-saver@2.0.1":
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.1.tgz#e18eb8b069e442f7b956d313f4fadd3ef887354e"
   integrity sha512-g1QUuhYVVAamfCifK7oB7G3aIl4BbOyzDOqVyUfEr4tfBKrXfeH+M+Tg7HKCXSrbzxYdhyCP7z9WbKo0R2hBCw==
@@ -3110,6 +3110,11 @@
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
 
+"@types/mousetrap@^1.6.3":
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.3.tgz#3159a01a2b21c9155a3d8f85588885d725dc987d"
+  integrity sha512-13gmo3M2qVvjQrWNseqM3+cR6S2Ss3grbR2NZltgMq94wOwqJYQdgn8qzwDshzgXqMlSUtyPZjysImmktu22ew==
+
 "@types/node@*":
   version "12.0.0"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.0.tgz#d11813b9c0ff8aaca29f04cbc12817f4c7d656e5"