From 208f3d4c6541df6d8b0bfcd70bc12d244eb045e9 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 2 Oct 2015 17:33:21 -0700 Subject: [PATCH] fix(typings): repair broken type-checking for StringMap Note that the previous type of StringMap was overly permissive and didn't catch errors. Also we have to explicitly type empty objects, which is explained here: https://github.com/Microsoft/TypeScript/issues/5089 Closes #4487 --- .../src/core/compiler/directive_metadata.ts | 10 +++++----- .../src/core/dom/generic_browser_adapter.ts | 2 +- .../angular2/src/core/dom/parse5_adapter.ts | 2 +- modules/angular2/src/core/facade/collection.ts | 4 ++-- .../angular2/src/core/forms/form_builder.ts | 2 +- modules/angular2/src/core/forms/validators.ts | 10 +++++----- .../src/core/linker/directive_resolver.ts | 4 ++-- .../src/core/linker/proto_view_factory.ts | 6 +++--- modules/angular2/src/core/pipes/date_pipe.ts | 2 +- modules/angular2/src/core/pipes/pipes.ts | 2 +- modules/angular2/src/core/zone/ng_zone.ts | 2 +- modules/angular2/src/http/headers.ts | 2 +- modules/angular2/src/router/route_registry.ts | 2 +- .../test/core/facade/collection_spec.ts | 18 +++++++++--------- modules/angular2/test/test_lib/utils_spec.ts | 2 +- .../test/metric/multi_metric_spec.ts | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/modules/angular2/src/core/compiler/directive_metadata.ts b/modules/angular2/src/core/compiler/directive_metadata.ts index fea72ea757..5024e8ba04 100644 --- a/modules/angular2/src/core/compiler/directive_metadata.ts +++ b/modules/angular2/src/core/compiler/directive_metadata.ts @@ -113,9 +113,9 @@ export class CompileDirectiveMetadata { lifecycleHooks?: LifecycleHooks[], template?: CompileTemplateMetadata } = {}): CompileDirectiveMetadata { - var hostListeners = {}; - var hostProperties = {}; - var hostAttributes = {}; + var hostListeners: {[key: string]: string} = {}; + var hostProperties: {[key: string]: string} = {}; + var hostAttributes: {[key: string]: string} = {}; if (isPresent(host)) { StringMapWrapper.forEach(host, (value: string, key: string) => { var matches = RegExpWrapper.firstMatch(HOST_REG_EXP, key); @@ -128,7 +128,7 @@ export class CompileDirectiveMetadata { } }); } - var inputsMap = {}; + var inputsMap: {[key: string]: string} = {}; if (isPresent(inputs)) { inputs.forEach((bindConfig: string) => { // canonical syntax: `dirProp: elProp` @@ -137,7 +137,7 @@ export class CompileDirectiveMetadata { inputsMap[parts[0]] = parts[1]; }); } - var outputsMap = {}; + var outputsMap: {[key: string]: string} = {}; if (isPresent(outputs)) { outputs.forEach((bindConfig: string) => { // canonical syntax: `dirProp: elProp` diff --git a/modules/angular2/src/core/dom/generic_browser_adapter.ts b/modules/angular2/src/core/dom/generic_browser_adapter.ts index 9a4fd8eb64..b2c5462806 100644 --- a/modules/angular2/src/core/dom/generic_browser_adapter.ts +++ b/modules/angular2/src/core/dom/generic_browser_adapter.ts @@ -23,7 +23,7 @@ export abstract class GenericBrowserDomAdapter extends DomAdapter { } } } - var transEndEventNames = { + var transEndEventNames: {[key: string]: string} = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', diff --git a/modules/angular2/src/core/dom/parse5_adapter.ts b/modules/angular2/src/core/dom/parse5_adapter.ts index b40c6b3c27..09df09e961 100644 --- a/modules/angular2/src/core/dom/parse5_adapter.ts +++ b/modules/angular2/src/core/dom/parse5_adapter.ts @@ -17,7 +17,7 @@ import { import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions'; import {SelectorMatcher, CssSelector} from 'angular2/src/core/compiler/selector'; -var _attrToPropMap = { +var _attrToPropMap: {[key: string]: string} = { 'class': 'className', 'innerHtml': 'innerHTML', 'readonly': 'readOnly', diff --git a/modules/angular2/src/core/facade/collection.ts b/modules/angular2/src/core/facade/collection.ts index c97b3d8d59..632612bfad 100644 --- a/modules/angular2/src/core/facade/collection.ts +++ b/modules/angular2/src/core/facade/collection.ts @@ -86,7 +86,7 @@ export class MapWrapper { return result; } static toStringMap(m: Map): {[key: string]: T} { - var r = {}; + var r: {[key: string]: T} = {}; m.forEach((v, k) => r[k] = v); return r; } @@ -135,7 +135,7 @@ export class StringMapWrapper { } static merge(m1: {[key: string]: V}, m2: {[key: string]: V}): {[key: string]: V} { - var m = {}; + var m: {[key: string]: V} = {}; for (var attr in m1) { if (m1.hasOwnProperty(attr)) { diff --git a/modules/angular2/src/core/forms/form_builder.ts b/modules/angular2/src/core/forms/form_builder.ts index c83a63c68f..76bcb97ac9 100644 --- a/modules/angular2/src/core/forms/form_builder.ts +++ b/modules/angular2/src/core/forms/form_builder.ts @@ -97,7 +97,7 @@ export class FormBuilder { } _reduceControls(controlsConfig: any): {[key: string]: modelModule.AbstractControl} { - var controls = {}; + var controls: {[key: string]: modelModule.AbstractControl} = {}; StringMapWrapper.forEach(controlsConfig, (controlConfig, controlName) => { controls[controlName] = this._createControl(controlConfig); }); diff --git a/modules/angular2/src/core/forms/validators.ts b/modules/angular2/src/core/forms/validators.ts index 56ef933ad1..08a738fdff 100644 --- a/modules/angular2/src/core/forms/validators.ts +++ b/modules/angular2/src/core/forms/validators.ts @@ -29,14 +29,14 @@ export class Validators { return function(control: modelModule.Control) { var res = ListWrapper.reduce(validators, (res, validator) => { var errors = validator(control); - return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res; + return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res; }, {}); return StringMapWrapper.isEmpty(res) ? null : res; }; } - static group(group: modelModule.ControlGroup): {[key: string]: boolean} { - var res = {}; + static group(group: modelModule.ControlGroup): {[key: string]: any[]} { + var res: {[key: string]: any[]} = {}; StringMapWrapper.forEach(group.controls, (control, name) => { if (group.contains(name) && isPresent(control.errors)) { Validators._mergeErrors(control, res); @@ -45,8 +45,8 @@ export class Validators { return StringMapWrapper.isEmpty(res) ? null : res; } - static array(array: modelModule.ControlArray): {[key: string]: boolean} { - var res = {}; + static array(array: modelModule.ControlArray): {[key: string]: any[]} { + var res: {[key: string]: any[]} = {}; array.controls.forEach((control) => { if (isPresent(control.errors)) { Validators._mergeErrors(control, res); diff --git a/modules/angular2/src/core/linker/directive_resolver.ts b/modules/angular2/src/core/linker/directive_resolver.ts index 81f884c20c..a5f71760e1 100644 --- a/modules/angular2/src/core/linker/directive_resolver.ts +++ b/modules/angular2/src/core/linker/directive_resolver.ts @@ -46,8 +46,8 @@ export class DirectiveResolver { propertyMetadata: {[key: string]: any[]}): DirectiveMetadata { var inputs = []; var outputs = []; - var host = {}; - var queries = {}; + var host: {[key: string]: string} = {}; + var queries: {[key: string]: any} = {}; StringMapWrapper.forEach(propertyMetadata, (metadata: any[], propName: string) => { metadata.forEach(a => { diff --git a/modules/angular2/src/core/linker/proto_view_factory.ts b/modules/angular2/src/core/linker/proto_view_factory.ts index e20b8f84f1..1b62d87f1d 100644 --- a/modules/angular2/src/core/linker/proto_view_factory.ts +++ b/modules/angular2/src/core/linker/proto_view_factory.ts @@ -55,9 +55,9 @@ export class ProtoViewFactory { var result = this._cache.get(compiledTemplate.id); if (isBlank(result)) { var templateData = compiledTemplate.getData(this._appId); - result = - new AppProtoView(templateData.commands, ViewType.HOST, true, - templateData.changeDetectorFactory, null, new ProtoPipes(new Map())); + var emptyMap: {[key: string]: PipeBinding} = {}; + result = new AppProtoView(templateData.commands, ViewType.HOST, true, + templateData.changeDetectorFactory, null, new ProtoPipes(emptyMap)); this._cache.set(compiledTemplate.id, result); } return result; diff --git a/modules/angular2/src/core/pipes/date_pipe.ts b/modules/angular2/src/core/pipes/date_pipe.ts index fa00f266b0..646df6c9a4 100644 --- a/modules/angular2/src/core/pipes/date_pipe.ts +++ b/modules/angular2/src/core/pipes/date_pipe.ts @@ -81,7 +81,7 @@ var defaultLocale: string = 'en-US'; @Pipe({name: 'date'}) @Injectable() export class DatePipe implements PipeTransform { - static _ALIASES = { + static _ALIASES: {[key: string]: String} = { 'medium': 'yMMMdjms', 'short': 'yMdjm', 'fullDate': 'yMMMMEEEEd', diff --git a/modules/angular2/src/core/pipes/pipes.ts b/modules/angular2/src/core/pipes/pipes.ts index 3a17607c14..f8b9de48ae 100644 --- a/modules/angular2/src/core/pipes/pipes.ts +++ b/modules/angular2/src/core/pipes/pipes.ts @@ -14,7 +14,7 @@ import * as cd from 'angular2/src/core/change_detection/pipes'; export class ProtoPipes { static fromBindings(bindings: PipeBinding[]): ProtoPipes { - var config = {}; + var config: {[key: string]: PipeBinding} = {}; bindings.forEach(b => config[b.name] = b); return new ProtoPipes(config); } diff --git a/modules/angular2/src/core/zone/ng_zone.ts b/modules/angular2/src/core/zone/ng_zone.ts index fbe8504fba..467a5f8c1d 100644 --- a/modules/angular2/src/core/zone/ng_zone.ts +++ b/modules/angular2/src/core/zone/ng_zone.ts @@ -251,7 +251,7 @@ export class NgZone { var errorHandling; if (enableLongStackTrace) { - errorHandling = StringMapWrapper.merge(Zone.longStackTraceZone, + errorHandling = StringMapWrapper.merge(Zone.longStackTraceZone, {onError: function(e) { ngZone._onError(this, e); }}); } else { errorHandling = {onError: function(e) { ngZone._onError(this, e); }}; diff --git a/modules/angular2/src/http/headers.ts b/modules/angular2/src/http/headers.ts index 77d235657c..d7362059a6 100644 --- a/modules/angular2/src/http/headers.ts +++ b/modules/angular2/src/http/headers.ts @@ -44,7 +44,7 @@ export class Headers { if (headers instanceof Headers) { this._headersMap = (headers)._headersMap; } else /*if (headers instanceof StringMap)*/ { - this._headersMap = MapWrapper.createFromStringMap(headers); + this._headersMap = MapWrapper.createFromStringMap(<{[key: string]: any}>headers); MapWrapper.forEach(this._headersMap, (v, k) => { if (!isListLikeIterable(v)) { var list = []; diff --git a/modules/angular2/src/router/route_registry.ts b/modules/angular2/src/router/route_registry.ts index 537af42175..05f36731c5 100644 --- a/modules/angular2/src/router/route_registry.ts +++ b/modules/angular2/src/router/route_registry.ts @@ -155,7 +155,7 @@ export class RouteRegistry { } var componentRecognizer = this._rules.get(parentComponent); - var auxInstructions = {}; + var auxInstructions: {[key: string]: Instruction} = {}; var promises = instruction.auxUrls.map((auxSegment: Url) => { var match = componentRecognizer.recognizeAuxiliary(auxSegment); diff --git a/modules/angular2/test/core/facade/collection_spec.ts b/modules/angular2/test/core/facade/collection_spec.ts index a04b005c76..702976780e 100644 --- a/modules/angular2/test/core/facade/collection_spec.ts +++ b/modules/angular2/test/core/facade/collection_spec.ts @@ -109,33 +109,33 @@ export function main() { () => { expect(StringMapWrapper.equals({}, {})).toBe(true); }); it('should return true when comparing the same map', () => { - var m1 = {'a': 1, 'b': 2, 'c': 3}; + var m1: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; expect(StringMapWrapper.equals(m1, m1)).toBe(true); }); it('should return true when comparing different maps with the same keys and values', () => { - var m1 = {'a': 1, 'b': 2, 'c': 3}; - var m2 = {'a': 1, 'b': 2, 'c': 3}; + var m1: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; + var m2: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; expect(StringMapWrapper.equals(m1, m2)).toBe(true); }); it('should return false when comparing maps with different numbers of keys', () => { - var m1 = {'a': 1, 'b': 2, 'c': 3}; - var m2 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}; + var m1: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; + var m2: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3, 'd': 4}; expect(StringMapWrapper.equals(m1, m2)).toBe(false); expect(StringMapWrapper.equals(m2, m1)).toBe(false); }); it('should return false when comparing maps with different keys', () => { - var m1 = {'a': 1, 'b': 2, 'c': 3}; - var m2 = {'a': 1, 'b': 2, 'CC': 3}; + var m1: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; + var m2: {[key: string]: number} = {'a': 1, 'b': 2, 'CC': 3}; expect(StringMapWrapper.equals(m1, m2)).toBe(false); expect(StringMapWrapper.equals(m2, m1)).toBe(false); }); it('should return false when comparing maps with different values', () => { - var m1 = {'a': 1, 'b': 2, 'c': 3}; - var m2 = {'a': 1, 'b': 20, 'c': 3}; + var m1: {[key: string]: number} = {'a': 1, 'b': 2, 'c': 3}; + var m2: {[key: string]: number} = {'a': 1, 'b': 20, 'c': 3}; expect(StringMapWrapper.equals(m1, m2)).toBe(false); expect(StringMapWrapper.equals(m2, m1)).toBe(false); }); diff --git a/modules/angular2/test/test_lib/utils_spec.ts b/modules/angular2/test/test_lib/utils_spec.ts index b78312cd61..372d2caa5a 100644 --- a/modules/angular2/test/test_lib/utils_spec.ts +++ b/modules/angular2/test/test_lib/utils_spec.ts @@ -187,7 +187,7 @@ export function main() { } ]; - browsers.forEach((browser) => { + browsers.forEach((browser: {[key: string]: any}) => { it(`should detect ${StringMapWrapper.get(browser, 'name')}`, () => { var bd = new BrowserDetection(StringMapWrapper.get(browser, 'ua')); expect(bd.isFirefox).toBe(StringMapWrapper.get(browser, 'isFirefox')); diff --git a/modules/benchpress/test/metric/multi_metric_spec.ts b/modules/benchpress/test/metric/multi_metric_spec.ts index 3478ec0f66..1ff982f6b5 100644 --- a/modules/benchpress/test/metric/multi_metric_spec.ts +++ b/modules/benchpress/test/metric/multi_metric_spec.ts @@ -77,7 +77,7 @@ class MockMetric extends Metric { } describe(): {[key: string]: string} { - var result = {}; + var result: {[key: string]: string} = {}; result[this._id] = 'describe'; return result; }