Skip to content

Commit 0769bc2

Browse files
fix(typescript): Make UI-Router noImplicitAny safe.
Closes #2693
1 parent a854e89 commit 0769bc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+645
-449
lines changed

src/common/common.ts

+73-51
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import {isFunction, isString, isArray, isRegExp, isDate} from "./predicates";
88
import { all, any, not, prop, curry } from "./hof";
99
import {services} from "./coreservices";
10+
import {State} from "../state/stateObject";
1011

1112
let w: any = typeof window === 'undefined' ? {} : window;
1213
let angular = w.angular || {};
@@ -16,15 +17,17 @@ export const copy = angular.copy || _copy;
1617
export const forEach = angular.forEach || _forEach;
1718
export const extend = angular.extend || _extend;
1819
export const equals = angular.equals || _equals;
19-
export const identity = (x) => x;
20-
export const noop = () => undefined;
20+
export const identity = (x: any) => x;
21+
export const noop = () => <any> undefined;
2122

2223
export type Mapper<X, T> = (x: X, key?: (string|number)) => T;
2324
export interface TypedMap<T> { [key: string]: T; }
24-
export type Predicate<X> = (X) => boolean;
25+
export type Predicate<X> = (x: X) => boolean;
2526
export type IInjectable = (Function|any[]);
2627

27-
export var abstractKey = 'abstract';
28+
export interface Obj extends Object {
29+
[key: string]: any
30+
}
2831

2932
/**
3033
* Binds and copies functions onto an object
@@ -81,7 +84,7 @@ export var abstractKey = 'abstract';
8184
* @param bindTo The object which the functions will be bound to
8285
* @param fnNames The function names which will be bound (Defaults to all the functions found on the 'from' object)
8386
*/
84-
export function bindFunctions(from, to, bindTo, fnNames: string[] = Object.keys(from)) {
87+
export function bindFunctions(from: Obj, to: Obj, bindTo: Obj, fnNames: string[] = Object.keys(from)) {
8588
return fnNames.filter(name => typeof from[name] === 'function')
8689
.forEach(name => to[name] = from[name].bind(bindTo));
8790
}
@@ -91,7 +94,7 @@ export function bindFunctions(from, to, bindTo, fnNames: string[] = Object.keys(
9194
* prototypal inheritance helper.
9295
* Creates a new object which has `parent` object as its prototype, and then copies the properties from `extra` onto it
9396
*/
94-
export const inherit = (parent, extra) =>
97+
export const inherit = (parent: Obj, extra: Obj) =>
9598
extend(new (extend(function() {}, { prototype: parent }))(), extra);
9699

97100
/**
@@ -117,13 +120,15 @@ export const inherit = (parent, extra) =>
117120
* pick(obj, "foo", "bar"); // returns { foo: 1, bar: 2 }
118121
* pick(obj, ["foo", "bar"]); // returns { foo: 1, bar: 2 }
119122
*/
120-
const restArgs = (args, idx = 0) => Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(args, idx));
123+
const restArgs = (args: IArguments, idx = 0) =>
124+
Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(args, idx));
121125

122126
/** Given an array, returns true if the object is found in the array, (using indexOf) */
123-
export const inArray = (array: any[], obj: any) => array.indexOf(obj) !== -1;
127+
export const inArray = (array: any[], obj: any) =>
128+
array.indexOf(obj) !== -1;
124129

125130
/** Given an array, and an item, if the item is found in the array, it removes it (in-place). The same array is returned */
126-
export const removeFrom = curry((array: any[], obj) => {
131+
export const removeFrom = curry((array: any[], obj: any) => {
127132
let idx = array.indexOf(obj);
128133
if (idx >= 0) array.splice(idx, 1);
129134
return array;
@@ -134,7 +139,7 @@ export const removeFrom = curry((array: any[], obj) => {
134139
* to only those properties of the objects in the defaultsList.
135140
* Earlier objects in the defaultsList take precedence when applying defaults.
136141
*/
137-
export function defaults(opts = {}, ...defaultsList) {
142+
export function defaults(opts = {}, ...defaultsList: Obj[]) {
138143
let defaults = merge.apply(null, [{}].concat(defaultsList));
139144
return extend({}, defaults, pick(opts || {}, Object.keys(defaults)));
140145
}
@@ -143,17 +148,17 @@ export function defaults(opts = {}, ...defaultsList) {
143148
* Merges properties from the list of objects to the destination object.
144149
* If a property already exists in the destination object, then it is not overwritten.
145150
*/
146-
export function merge(dst, ...objs: Object[]) {
147-
forEach(objs, function(obj) {
148-
forEach(obj, function(value, key) {
151+
export function merge(dst: Obj, ...objs: Obj[]) {
152+
forEach(objs, function(obj: Obj) {
153+
forEach(obj, function(value: any, key: string) {
149154
if (!dst.hasOwnProperty(key)) dst[key] = value;
150155
});
151156
});
152157
return dst;
153158
}
154159

155160
/** Reduce function that merges each element of the list into a single object, using extend */
156-
export const mergeR = (memo, item) => extend(memo, item);
161+
export const mergeR = (memo: Obj, item: Obj) => extend(memo, item);
157162

158163
/**
159164
* Finds the common ancestor path between two states.
@@ -162,8 +167,8 @@ export const mergeR = (memo, item) => extend(memo, item);
162167
* @param {Object} second The second state.
163168
* @return {Array} Returns an array of state names in descending order, not including the root.
164169
*/
165-
export function ancestors(first, second) {
166-
let path = [];
170+
export function ancestors(first: State, second: State) {
171+
let path: State[] = [];
167172

168173
for (var n in first.path) {
169174
if (first.path[n] !== second.path[n]) break;
@@ -181,18 +186,18 @@ export function ancestors(first, second) {
181186
* it defaults to the list of keys in `a`.
182187
* @return {Boolean} Returns `true` if the keys match, otherwise `false`.
183188
*/
184-
export function equalForKeys(a, b, keys: string[] = Object.keys(a)) {
189+
export function equalForKeys(a: Obj, b: Obj, keys: string[] = Object.keys(a)) {
185190
for (var i = 0; i < keys.length; i++) {
186191
let k = keys[i];
187192
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
188193
}
189194
return true;
190195
}
191196

192-
type PickOmitPredicate = (keys: string[], key) => boolean;
193-
function pickOmitImpl(predicate: PickOmitPredicate, obj) {
194-
let objCopy = {}, keys = restArgs(arguments, 2);
195-
for (var key in obj) {
197+
type PickOmitPredicate = (keys: string[], key: string) => boolean;
198+
function pickOmitImpl(predicate: PickOmitPredicate, obj: Obj, ...keys: string[]) {
199+
let objCopy = {};
200+
for (let key in obj) {
196201
if (predicate(keys, key)) objCopy[key] = obj[key];
197202
}
198203
return objCopy;
@@ -208,7 +213,7 @@ function pickOmitImpl(predicate: PickOmitPredicate, obj) {
208213
* @param obj the source object
209214
* @param propNames an Array of strings, which are the whitelisted property names
210215
*/
211-
export function pick(obj, propNames: string[]): Object;
216+
export function pick(obj: Obj, propNames: string[]): Obj;
212217
/**
213218
* @example
214219
* ```
@@ -219,9 +224,11 @@ export function pick(obj, propNames: string[]): Object;
219224
* @param obj the source object
220225
* @param propNames 1..n strings, which are the whitelisted property names
221226
*/
222-
export function pick(obj, ...propNames: string[]): Object;
227+
export function pick(obj: Obj, ...propNames: string[]): Obj;
223228
/** Return a copy of the object only containing the whitelisted properties. */
224-
export function pick(obj) { return pickOmitImpl.apply(null, [inArray].concat(restArgs(arguments))); }
229+
export function pick(obj: Obj) {
230+
return pickOmitImpl.apply(null, [inArray].concat(restArgs(arguments)));
231+
}
225232

226233
/**
227234
* @example
@@ -233,7 +240,7 @@ export function pick(obj) { return pickOmitImpl.apply(null, [inArray].concat(res
233240
* @param obj the source object
234241
* @param propNames an Array of strings, which are the blacklisted property names
235242
*/
236-
export function omit(obj, propNames: string[]): Object;
243+
export function omit(obj: Obj, propNames: string[]): Obj;
237244
/**
238245
* @example
239246
* ```
@@ -244,29 +251,32 @@ export function omit(obj, propNames: string[]): Object;
244251
* @param obj the source object
245252
* @param propNames 1..n strings, which are the blacklisted property names
246253
*/
247-
export function omit(obj, ...propNames: string[]): Object;
254+
export function omit(obj: Obj, ...propNames: string[]): Obj;
248255
/** Return a copy of the object omitting the blacklisted properties. */
249-
export function omit(obj) { return pickOmitImpl.apply(null, [not(inArray)].concat(restArgs(arguments))); }
256+
export function omit(obj: Obj) {
257+
let notInArray = (array, item) => !inArray(array, item);
258+
return pickOmitImpl.apply(null, [notInArray].concat(restArgs(arguments)));
259+
}
250260

251261

252262
/** Given an array of objects, maps each element to a named property of the element. */
253-
export function pluck(collection: any[], propName: string): any[];
263+
export function pluck(collection: Obj[], propName: string): Obj[];
254264
/** Given an object, maps each property of the object to a named property of the property. */
255265
export function pluck(collection: { [key: string]: any }, propName: string): { [key: string]: any };
256266
/**
257267
* Maps an array, or object to a property (by name)
258268
*/
259-
export function pluck(collection, propName): any {
269+
export function pluck(collection: any, propName: string): any {
260270
return map(collection, <Mapper<any, string>> prop(propName));
261271
}
262272

263273

264274
/** Given an array of objects, returns a new array containing only the elements which passed the callback predicate */
265-
export function filter<T>(collection: T[], callback: (T, key?) => boolean): T[];
275+
export function filter<T>(collection: T[], callback: (t: T, key?: number) => boolean): T[];
266276
/** Given an object, returns a new object with only those properties that passed the callback predicate */
267-
export function filter<T>(collection: TypedMap<T>, callback: (T, key?) => boolean): TypedMap<T>;
277+
export function filter<T>(collection: TypedMap<T>, callback: (t: T, key?: string) => boolean): TypedMap<T>;
268278
/** Filters an Array or an Object's properties based on a predicate */
269-
export function filter<T>(collection: T, callback: Function): T {
279+
export function filter<T>(collection: any, callback: Function): T {
270280
let arr = isArray(collection), result: any = arr ? [] : {};
271281
let accept = arr ? x => result.push(x) : (x, key) => result[key] = x;
272282
forEach(collection, function(item, i) {
@@ -281,7 +291,7 @@ export function find<T>(collection: TypedMap<T>, callback: Predicate<T>): T;
281291
/** Given an array of objects, returns the first object which passed the callback predicate */
282292
export function find<T>(collection: T[], callback: Predicate<T>): T;
283293
/** Finds an object from an array, or a property of an object, that matches a predicate */
284-
export function find(collection, callback) {
294+
export function find(collection: any, callback: any) {
285295
let result;
286296

287297
forEach(collection, function(item, i) {
@@ -314,7 +324,8 @@ export function map(collection: any, callback: any): any {
314324
* let vals = values(foo); // [ 1, 2, 3 ]
315325
* ```
316326
*/
317-
export const values: (<T> (obj: TypedMap<T>) => T[]) = (obj) => Object.keys(obj).map(key => obj[key]);
327+
export const values: (<T> (obj: TypedMap<T>) => T[]) = (obj: Obj) =>
328+
Object.keys(obj).map(key => obj[key]);
318329

319330
/**
320331
* Reduce function that returns true if all of the values are truthy.
@@ -329,7 +340,7 @@ export const values: (<T> (obj: TypedMap<T>) => T[]) = (obj) => Object.keys(obj)
329340
* vals.reduce(allTrueR, true); // false
330341
* ```
331342
*/
332-
export const allTrueR = (memo: boolean, elem) => memo && elem;
343+
export const allTrueR = (memo: boolean, elem: any) => memo && elem;
333344

334345
/**
335346
* Reduce function that returns true if any of the values are truthy.
@@ -344,7 +355,7 @@ export const allTrueR = (memo: boolean, elem) => memo && elem;
344355
* vals.reduce(anyTrueR, true); // true
345356
* ```
346357
*/
347-
export const anyTrueR = (memo: boolean, elem) => memo || elem;
358+
export const anyTrueR = (memo: boolean, elem: any) => memo || elem;
348359

349360
/**
350361
* Reduce function which un-nests a single level of arrays
@@ -355,7 +366,7 @@ export const anyTrueR = (memo: boolean, elem) => memo || elem;
355366
* input.reduce(unnestR, []) // [ "a", "b", "c", "d", [ "double, "nested" ] ]
356367
* ```
357368
*/
358-
export const unnestR = (memo: any[], elem) => memo.concat(elem);
369+
export const unnestR = (memo: any[], elem: any[]) => memo.concat(elem);
359370

360371
/**
361372
* Reduce function which recursively un-nests all arrays
@@ -367,12 +378,18 @@ export const unnestR = (memo: any[], elem) => memo.concat(elem);
367378
* input.reduce(unnestR, []) // [ "a", "b", "c", "d", "double, "nested" ]
368379
* ```
369380
*/
370-
export const flattenR = (memo: any[], elem) => isArray(elem) ? memo.concat(elem.reduce(flattenR, [])) : pushR(memo, elem);
381+
export const flattenR = (memo: any[], elem: any) =>
382+
isArray(elem) ? memo.concat(elem.reduce(flattenR, [])) : pushR(memo, elem);
383+
371384
/** Reduce function that pushes an object to an array, then returns the array. Mostly just for [[flattenR]] */
372-
export function pushR(arr: any[], obj) { arr.push(obj); return arr; }
385+
export function pushR(arr: any[], obj: any) {
386+
arr.push(obj);
387+
return arr;
388+
}
373389

374390
/** Reduce function that filters out duplicates */
375-
export const uniqR = (acc, token) => inArray(acc, token) ? acc : pushR(acc, token);
391+
export const uniqR = (acc: any[], token: any) =>
392+
inArray(acc, token) ? acc : pushR(acc, token);
376393

377394
/**
378395
* Return a new array with a single level of arrays unnested.
@@ -428,7 +445,8 @@ export function assertPredicate<T>(predicate: Predicate<T>, errMsg: (string|Func
428445
* pairs({ foo: "FOO", bar: "BAR }) // [ [ "foo", "FOO" ], [ "bar": "BAR" ] ]
429446
* ```
430447
*/
431-
export const pairs = (object) => Object.keys(object).map(key => [ key, object[key]] );
448+
export const pairs = (obj: Obj) =>
449+
Object.keys(obj).map(key => [ key, obj[key]] );
432450

433451
/**
434452
* Given two or more parallel arrays, returns an array of tuples where
@@ -471,7 +489,7 @@ export function arrayTuples(...arrayArgs: any[]): any[] {
471489
* ```
472490
*/
473491
export function applyPairs(memo: TypedMap<any>, keyValTuple: any[]) {
474-
let key, value;
492+
let key: string, value: any;
475493
if (isArray(keyValTuple)) [key, value] = keyValTuple;
476494
if (!isString(key)) throw new Error("invalid parameters to applyPairs");
477495
memo[key] = value;
@@ -489,25 +507,29 @@ export function tail<T>(arr: T[]): T {
489507
* note: This is a shallow copy, while angular.copy is a deep copy.
490508
* ui-router uses `copy` only to make copies of state parameters.
491509
*/
492-
function _copy(src, dest) {
510+
function _copy(src: Obj, dest: Obj) {
493511
if (dest) Object.keys(dest).forEach(key => delete dest[key]);
494512
if (!dest) dest = {};
495513
return extend(dest, src);
496514
}
497515

498-
function _forEach(obj: (any[]|any), cb, _this) {
516+
/** Naive forEach implementation works with Objects or Arrays */
517+
function _forEach(obj: (any[]|any), cb: Function, _this: Obj) {
499518
if (isArray(obj)) return obj.forEach(cb, _this);
500519
Object.keys(obj).forEach(key => cb(obj[key], key));
501520
}
502521

503-
function _copyProps(to, from) { Object.keys(from).forEach(key => to[key] = from[key]); return to; }
504-
function _extend(toObj, fromObj);
505-
function _extend(toObj, ...fromObj);
506-
function _extend(toObj, rest) {
522+
function _copyProps(to: Obj, from: Obj) {
523+
Object.keys(from).forEach(key => to[key] = from[key]);
524+
return to;
525+
}
526+
function _extend(toObj: Obj, fromObj: Obj): Obj;
527+
function _extend(toObj: Obj, ...fromObj: Obj[]): Obj;
528+
function _extend(toObj: Obj) {
507529
return restArgs(arguments, 1).filter(identity).reduce(_copyProps, toObj);
508530
}
509531

510-
function _equals(o1, o2) {
532+
function _equals(o1: any, o2: any): boolean {
511533
if (o1 === o2) return true;
512534
if (o1 === null || o2 === null) return false;
513535
if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
@@ -523,7 +545,7 @@ function _equals(o1, o2) {
523545
let predicates = [isFunction, isArray, isDate, isRegExp];
524546
if (predicates.map(any).reduce((b, fn) => b || !!fn(tup), false)) return false;
525547

526-
let key, keys = {};
548+
let key: string, keys: { [i: string]: boolean } = {};
527549
for (key in o1) {
528550
if (!_equals(o1[key], o2[key])) return false;
529551
keys[key] = true;
@@ -535,7 +557,7 @@ function _equals(o1, o2) {
535557
return true;
536558
}
537559

538-
function _arraysEq(a1, a2) {
560+
function _arraysEq(a1: any[], a2: any[]) {
539561
if (a1.length !== a2.length) return false;
540562
return arrayTuples(a1, a2).reduce((b, t) => b && _equals(t[0], t[1]), true);
541563
}

0 commit comments

Comments
 (0)