fix(common): Update types for TypeScript nullability support

This commit is contained in:
Miško Hevery 2017-03-24 09:54:02 -07:00 committed by Hans
parent 4c566dbfbb
commit d8b73e4223
29 changed files with 126 additions and 117 deletions

View File

@ -38,8 +38,8 @@ import {Directive, DoCheck, ElementRef, Input, IterableChanges, IterableDiffer,
*/
@Directive({selector: '[ngClass]'})
export class NgClass implements DoCheck {
private _iterableDiffer: IterableDiffer<string>;
private _keyValueDiffer: KeyValueDiffer<string, any>;
private _iterableDiffer: IterableDiffer<string>|null;
private _keyValueDiffer: KeyValueDiffer<string, any>|null;
private _initialClasses: string[] = [];
private _rawClass: string[]|Set<string>|{[klass: string]: any};

View File

@ -73,8 +73,8 @@ export class NgComponentOutlet implements OnChanges, OnDestroy {
@Input() ngComponentOutletContent: any[][];
@Input() ngComponentOutletNgModuleFactory: NgModuleFactory<any>;
private _componentRef: ComponentRef<any> = null;
private _moduleRef: NgModuleRef<any> = null;
private _componentRef: ComponentRef<any>|null = null;
private _moduleRef: NgModuleRef<any>|null = null;
constructor(private _viewContainerRef: ViewContainerRef) {}

View File

@ -114,7 +114,7 @@ export class NgForOf<T> implements DoCheck, OnChanges {
get ngForTrackBy(): TrackByFunction<T> { return this._trackByFn; }
private _differ: IterableDiffer<T> = null;
private _differ: IterableDiffer<T>|null = null;
private _trackByFn: TrackByFunction<T>;
constructor(
@ -159,13 +159,13 @@ export class NgForOf<T> implements DoCheck, OnChanges {
(item: IterableChangeRecord<any>, adjustedPreviousIndex: number, currentIndex: number) => {
if (item.previousIndex == null) {
const view = this._viewContainer.createEmbeddedView(
this._template, new NgForOfContext(null, this.ngForOf, null, null), currentIndex);
const tuple = new RecordViewTuple(item, view);
this._template, new NgForOfContext<T>(null !, this.ngForOf, -1, -1), currentIndex);
const tuple = new RecordViewTuple<T>(item, view);
insertTuples.push(tuple);
} else if (currentIndex == null) {
this._viewContainer.remove(adjustedPreviousIndex);
} else {
const view = this._viewContainer.get(adjustedPreviousIndex);
const view = this._viewContainer.get(adjustedPreviousIndex) !;
this._viewContainer.move(view, currentIndex);
const tuple = new RecordViewTuple(item, <EmbeddedViewRef<NgForOfContext<T>>>view);
insertTuples.push(tuple);

View File

@ -102,10 +102,10 @@ import {Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef} from '
@Directive({selector: '[ngIf]'})
export class NgIf {
private _context: NgIfContext = new NgIfContext();
private _thenTemplateRef: TemplateRef<NgIfContext> = null;
private _elseTemplateRef: TemplateRef<NgIfContext> = null;
private _thenViewRef: EmbeddedViewRef<NgIfContext> = null;
private _elseViewRef: EmbeddedViewRef<NgIfContext> = null;
private _thenTemplateRef: TemplateRef<NgIfContext>|null = null;
private _elseTemplateRef: TemplateRef<NgIfContext>|null = null;
private _thenViewRef: EmbeddedViewRef<NgIfContext>|null = null;
private _elseViewRef: EmbeddedViewRef<NgIfContext>|null = null;
constructor(private _viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext>) {
this._thenTemplateRef = templateRef;

View File

@ -61,7 +61,7 @@ export class NgStyle implements DoCheck {
changes.forEachChangedItem((record) => this._setStyle(record.key, record.currentValue));
}
private _setStyle(nameAndUnit: string, value: string|number): void {
private _setStyle(nameAndUnit: string, value: string|number|null|undefined): void {
const [name, unit] = nameAndUnit.split('.');
value = value != null && unit ? `${value}${unit}` : value;

View File

@ -66,7 +66,8 @@ export class HashLocationStrategy extends LocationStrategy {
}
pushState(state: any, title: string, path: string, queryParams: string) {
let url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
let url: string|null =
this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams));
if (url.length == 0) {
url = this._platformLocation.pathname;
}

View File

@ -128,8 +128,8 @@ export class Location {
* Subscribe to the platform's `popState` events.
*/
subscribe(
onNext: (value: PopStateEvent) => void, onThrow: (exception: any) => void = null,
onReturn: () => void = null): Object {
onNext: (value: PopStateEvent) => void, onThrow?: ((exception: any) => void)|null,
onReturn?: (() => void)|null): Object {
return this._subject.subscribe({next: onNext, error: onThrow, complete: onReturn});
}

View File

@ -38,9 +38,9 @@ export abstract class PlatformLocation {
abstract onPopState(fn: LocationChangeListener): void;
abstract onHashChange(fn: LocationChangeListener): void;
get pathname(): string { return null; }
get search(): string { return null; }
get hash(): string { return null; }
abstract get pathname(): string;
abstract get search(): string;
abstract get hash(): string;
abstract replaceState(state: any, title: string, url: string): void;

View File

@ -8,33 +8,34 @@
import {ChangeDetectorRef, EventEmitter, OnDestroy, Pipe, PipeTransform, WrappedValue, ɵisObservable, ɵisPromise} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {ISubscription} from 'rxjs/Subscription';
import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
interface SubscriptionStrategy {
createSubscription(async: any, updateLatestValue: any): any;
dispose(subscription: any): void;
onDestroy(subscription: any): void;
createSubscription(async: Observable<any>|Promise<any>, updateLatestValue: any): ISubscription
|Promise<any>;
dispose(subscription: ISubscription|Promise<any>): void;
onDestroy(subscription: ISubscription|Promise<any>): void;
}
class ObservableStrategy implements SubscriptionStrategy {
createSubscription(async: any, updateLatestValue: any): any {
createSubscription(async: Observable<any>, updateLatestValue: any): ISubscription {
return async.subscribe({next: updateLatestValue, error: (e: any) => { throw e; }});
}
dispose(subscription: any): void { subscription.unsubscribe(); }
dispose(subscription: ISubscription): void { subscription.unsubscribe(); }
onDestroy(subscription: any): void { subscription.unsubscribe(); }
onDestroy(subscription: ISubscription): void { subscription.unsubscribe(); }
}
class PromiseStrategy implements SubscriptionStrategy {
createSubscription(async: Promise<any>, updateLatestValue: (v: any) => any): any {
createSubscription(async: Promise<any>, updateLatestValue: (v: any) => any): Promise<any> {
return async.then(updateLatestValue, e => { throw e; });
}
dispose(subscription: any): void {}
dispose(subscription: Promise<any>): void {}
onDestroy(subscription: any): void {}
onDestroy(subscription: Promise<any>): void {}
}
const _promiseStrategy = new PromiseStrategy();
@ -67,12 +68,12 @@ const _observableStrategy = new ObservableStrategy();
*/
@Pipe({name: 'async', pure: false})
export class AsyncPipe implements OnDestroy, PipeTransform {
private _latestValue: Object = null;
private _latestReturnedValue: Object = null;
private _latestValue: any = null;
private _latestReturnedValue: any = null;
private _subscription: Object = null;
private _obj: Observable<any>|Promise<any>|EventEmitter<any> = null;
private _strategy: SubscriptionStrategy = null;
private _subscription: ISubscription|Promise<any>|null = null;
private _obj: Observable<any>|Promise<any>|EventEmitter<any>|null = null;
private _strategy: SubscriptionStrategy = null !;
constructor(private _ref: ChangeDetectorRef) {}
@ -82,10 +83,11 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
}
}
transform<T>(obj: null): null;
transform<T>(obj: undefined): undefined;
transform<T>(obj: Observable<T>): T|null;
transform<T>(obj: Promise<T>): T|null;
transform<T>(obj: EventEmitter<T>): T|null;
transform(obj: Observable<any>|Promise<any>|EventEmitter<any>): any {
transform(obj: Observable<any>|Promise<any>|null|undefined): any {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
@ -127,7 +129,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
}
private _dispose(): void {
this._strategy.dispose(this._subscription);
this._strategy.dispose(this._subscription !);
this._latestValue = null;
this._latestReturnedValue = null;
this._subscription = null;

View File

@ -100,7 +100,7 @@ export class DatePipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private _locale: string) {}
transform(value: any, pattern: string = 'mediumDate'): string {
transform(value: any, pattern: string = 'mediumDate'): string|null {
let date: Date;
if (isBlank(value) || value !== value) return null;
@ -130,7 +130,7 @@ export class DatePipe implements PipeTransform {
}
if (!isDate(date)) {
let match: RegExpMatchArray;
let match: RegExpMatchArray|null;
if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) {
date = isoStringToDate(match);
} else {

View File

@ -28,7 +28,7 @@ import {invalidPipeArgumentError} from './invalid_pipe_argument_error';
*/
@Pipe({name: 'i18nSelect', pure: true})
export class I18nSelectPipe implements PipeTransform {
transform(value: string, mapping: {[key: string]: string}): string {
transform(value: string|null|undefined, mapping: {[key: string]: string}): string {
if (value == null) return '';
if (typeof mapping !== 'object' || typeof value !== 'string') {

View File

@ -20,7 +20,7 @@ export class NumberFormatter {
minimumIntegerDigits?: number,
minimumFractionDigits?: number,
maximumFractionDigits?: number,
currency?: string,
currency?: string|null,
currencyAsSymbol?: boolean
} = {}): string {
const options: Intl.NumberFormatOptions = {
@ -31,7 +31,7 @@ export class NumberFormatter {
};
if (style == NumberFormatStyle.Currency) {
options.currency = currency;
options.currency = typeof currency == 'string' ? currency : undefined;
options.currencyDisplay = currencyAsSymbol ? 'symbol' : 'code';
}
return new Intl.NumberFormat(locale, options).format(num);
@ -192,17 +192,18 @@ function dateFormatter(format: string, date: Date, locale: string): string {
if (!parts) {
parts = [];
let match: RegExpExecArray;
let match: RegExpExecArray|null;
DATE_FORMATS_SPLIT.exec(format);
while (format) {
match = DATE_FORMATS_SPLIT.exec(format);
let _format: string|null = format;
while (_format) {
match = DATE_FORMATS_SPLIT.exec(_format);
if (match) {
parts = parts.concat(match.slice(1));
format = parts.pop();
_format = parts.pop() !;
} else {
parts.push(format);
format = null;
parts.push(_format);
_format = null;
}
}

View File

@ -14,7 +14,8 @@ const _NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
function formatNumber(
pipe: Type<any>, locale: string, value: number | string, style: NumberFormatStyle,
digits: string, currency: string = null, currencyAsSymbol: boolean = false): string {
digits?: string | null, currency: string | null = null,
currencyAsSymbol: boolean = false): string|null {
if (value == null) return null;
// Convert strings to numbers
@ -23,9 +24,9 @@ function formatNumber(
throw invalidPipeArgumentError(pipe, value);
}
let minInt: number;
let minFraction: number;
let maxFraction: number;
let minInt: number|undefined = undefined;
let minFraction: number|undefined = undefined;
let maxFraction: number|undefined = undefined;
if (style !== NumberFormatStyle.Currency) {
// rely on Intl default for currency
minInt = 1;
@ -89,7 +90,7 @@ function formatNumber(
export class DecimalPipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private _locale: string) {}
transform(value: any, digits: string = null): string {
transform(value: any, digits?: string): string|null {
return formatNumber(DecimalPipe, this._locale, value, NumberFormatStyle.Decimal, digits);
}
}
@ -118,7 +119,7 @@ export class DecimalPipe implements PipeTransform {
export class PercentPipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private _locale: string) {}
transform(value: any, digits: string = null): string {
transform(value: any, digits?: string): string|null {
return formatNumber(PercentPipe, this._locale, value, NumberFormatStyle.Percent, digits);
}
}
@ -153,7 +154,7 @@ export class CurrencyPipe implements PipeTransform {
transform(
value: any, currencyCode: string = 'USD', symbolDisplay: boolean = false,
digits: string = null): string {
digits?: string): string|null {
return formatNumber(
CurrencyPipe, this._locale, value, NumberFormatStyle.Currency, digits, currencyCode,
symbolDisplay);

View File

@ -11,19 +11,19 @@ import {ComponentFixture, TestBed, async} from '@angular/core/testing';
export function main() {
describe('binding to CSS class list', () => {
let fixture: ComponentFixture<any>;
let fixture: ComponentFixture<any>|null;
function normalizeClassNames(classes: string) {
return classes.trim().split(' ').sort().join(' ');
}
function detectChangesAndExpectClassName(classes: string): void {
fixture.detectChanges();
let nonNormalizedClassName = fixture.debugElement.children[0].nativeElement.className;
fixture !.detectChanges();
let nonNormalizedClassName = fixture !.debugElement.children[0].nativeElement.className;
expect(normalizeClassNames(nonNormalizedClassName)).toEqual(normalizeClassNames(classes));
}
function getComponent(): TestComponent { return fixture.debugElement.componentInstance; }
function getComponent(): TestComponent { return fixture !.debugElement.componentInstance; }
afterEach(() => { fixture = null; });
@ -74,13 +74,13 @@ export function main() {
detectChangesAndExpectClassName('foo');
objExpr['bar'] = true;
objExpr !['bar'] = true;
detectChangesAndExpectClassName('foo bar');
objExpr['baz'] = true;
objExpr !['baz'] = true;
detectChangesAndExpectClassName('foo bar baz');
delete (objExpr['bar']);
delete (objExpr !['bar']);
detectChangesAndExpectClassName('foo baz');
}));
@ -194,7 +194,7 @@ export function main() {
it('should throw with descriptive error message when CSS class is not a string', () => {
fixture = createTestComponent(`<div [ngClass]="['foo', {}]"></div>`);
expect(() => fixture.detectChanges())
expect(() => fixture !.detectChanges())
.toThrowError(
/NgClass can only toggle CSS classes expressed as strings, got \[object Object\]/);
});
@ -266,10 +266,10 @@ export function main() {
fixture = createTestComponent('<div [ngClass]="objExpr" class="init foo"></div>');
const objExpr = getComponent().objExpr;
objExpr['bar'] = true;
objExpr !['bar'] = true;
detectChangesAndExpectClassName('init foo bar');
objExpr['foo'] = false;
objExpr !['foo'] = false;
detectChangesAndExpectClassName('init bar');
getComponent().objExpr = null;
@ -280,10 +280,10 @@ export function main() {
fixture = createTestComponent(`<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`);
const objExpr = getComponent().objExpr;
objExpr['bar'] = true;
objExpr !['bar'] = true;
detectChangesAndExpectClassName(`init foo bar`);
objExpr['foo'] = false;
objExpr !['foo'] = false;
detectChangesAndExpectClassName(`init bar`);
getComponent().objExpr = null;
@ -295,10 +295,10 @@ export function main() {
createTestComponent(`<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`);
const objExpr = getComponent().objExpr;
objExpr['bar'] = true;
objExpr !['bar'] = true;
detectChangesAndExpectClassName(`init foo bar`);
objExpr['foo'] = false;
objExpr !['foo'] = false;
detectChangesAndExpectClassName(`init bar`);
getComponent().objExpr = null;
@ -313,10 +313,10 @@ export function main() {
detectChangesAndExpectClassName('init foo baz');
objExpr['bar'] = true;
objExpr !['bar'] = true;
detectChangesAndExpectClassName('init foo baz bar');
objExpr['foo'] = false;
objExpr !['foo'] = false;
detectChangesAndExpectClassName('init baz bar');
getComponent().condition = false;
@ -331,7 +331,7 @@ export function main() {
detectChangesAndExpectClassName('init foo');
cmp.objExpr['bar'] = true;
cmp.objExpr !['bar'] = true;
detectChangesAndExpectClassName('init foo bar');
cmp.strExpr = 'baz';
@ -350,8 +350,8 @@ class TestComponent {
items: any[];
arrExpr: string[] = ['foo'];
setExpr: Set<string> = new Set<string>();
objExpr: {[klass: string]: any} = {'foo': true, 'bar': false};
strExpr = 'foo';
objExpr: {[klass: string]: any}|null = {'foo': true, 'bar': false};
strExpr: string|null = 'foo';
constructor() { this.setExpr.add('foo'); }
}

View File

@ -52,7 +52,7 @@ export function main() {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo');
expect(fixture.componentInstance.cmpRef).toBeAnInstanceOf(ComponentRef);
expect(fixture.componentInstance.cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(fixture.componentInstance.cmpRef !.instance).toBeAnInstanceOf(InjectedComponent);
}));
@ -100,7 +100,7 @@ export function main() {
[{provide: TEST_TOKEN, useValue: uniqueValue}], fixture.componentRef.injector);
fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef;
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBe(uniqueValue);
@ -113,7 +113,7 @@ export function main() {
fixture.componentInstance.cmpRef = null;
fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef;
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBeNull();
@ -169,9 +169,9 @@ export function main() {
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'];
spyOn(moduleRef, 'destroy').and.callThrough();
expect(moduleRef.destroy).not.toHaveBeenCalled();
expect(moduleRef !.destroy).not.toHaveBeenCalled();
fixture.destroy();
expect(moduleRef.destroy).toHaveBeenCalled();
expect(moduleRef !.destroy).toHaveBeenCalled();
}));
it('should not re-create moduleRef when it didn\'t actually change', async(() => {
@ -224,13 +224,13 @@ const TEST_CMP_TEMPLATE =
`<ng-template *ngComponentOutlet="currentComponent; injector: injector; content: projectables; ngModuleFactory: module;"></ng-template>`;
@Component({selector: 'test-cmp', template: TEST_CMP_TEMPLATE})
class TestComponent {
currentComponent: Type<any>;
currentComponent: Type<any>|null;
injector: Injector;
projectables: any[][];
module: NgModuleFactory<any>;
get cmpRef(): ComponentRef<any> { return this.ngComponentOutlet['_componentRef']; }
set cmpRef(value: ComponentRef<any>) { this.ngComponentOutlet['_componentRef'] = value; }
get cmpRef(): ComponentRef<any>|null { return this.ngComponentOutlet['_componentRef']; }
set cmpRef(value: ComponentRef<any>|null) { this.ngComponentOutlet['_componentRef'] = value; }
@ViewChildren(TemplateRef) tplRefs: QueryList<TemplateRef<any>>;
@ViewChild(NgComponentOutlet) ngComponentOutlet: NgComponentOutlet;

View File

@ -25,7 +25,7 @@ export function main() {
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null as any; });
beforeEach(() => {
TestBed.configureTestingModule({
@ -103,7 +103,7 @@ export function main() {
detectChangesAndExpectText('1;2;');
getComponent().items = null;
getComponent().items = null !;
detectChangesAndExpectText('');
getComponent().items = [1, 2, 3];

View File

@ -19,7 +19,7 @@ export function main() {
function getComponent(): TestComponent { return fixture.componentInstance; }
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null !; });
beforeEach(() => {
TestBed.configureTestingModule({

View File

@ -22,7 +22,7 @@ export function main() {
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null !; });
beforeEach(() => {
TestBed.configureTestingModule({
@ -153,7 +153,7 @@ class TestLocalization extends NgLocalization {
@Component({selector: 'test-cmp', template: ''})
class TestComponent {
switchValue: number = null;
switchValue: number|null = null;
}
function createTestComponent(template: string): ComponentFixture<TestComponent> {

View File

@ -20,7 +20,7 @@ export function main() {
return expect(fixture.debugElement.children[0].nativeElement);
}
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null !; });
beforeEach(() => {
TestBed.configureTestingModule({declarations: [TestComponent], imports: [CommonModule]});

View File

@ -22,7 +22,7 @@ export function main() {
expect(fixture.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null !; });
beforeEach(() => {
TestBed.configureTestingModule({

View File

@ -22,7 +22,7 @@ export function main() {
expect(fixture.debugElement.nativeElement).toHaveText(text);
}
afterEach(() => { fixture = null; });
afterEach(() => { fixture = null as any; });
beforeEach(() => {
TestBed.configureTestingModule({
@ -61,7 +61,7 @@ export function main() {
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
@ -77,7 +77,7 @@ export function main() {
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references['refs'];
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');

View File

@ -201,14 +201,14 @@ export function main() {
describe('null', () => {
it('should return null when given null', () => {
const pipe = new AsyncPipe(null);
const pipe = new AsyncPipe(null as any);
expect(pipe.transform(null)).toEqual(null);
});
});
describe('other types', () => {
it('should throw when given an invalid object', () => {
const pipe = new AsyncPipe(null);
const pipe = new AsyncPipe(null as any);
expect(() => pipe.transform(<any>'some bogus object')).toThrowError();
});
});

View File

@ -197,7 +197,7 @@ export function main() {
() => expect(pipe.transform('2017-01-20T19:00:00+0000')).toEqual('Jan 20, 2017'));
it('should remove bidi control characters',
() => expect(pipe.transform(date, 'MM/dd/yyyy').length).toEqual(10));
() => expect(pipe.transform(date, 'MM/dd/yyyy') !.length).toEqual(10));
});
});
}

View File

@ -52,7 +52,7 @@ export function main() {
});
it('should use "" if value is undefined', () => {
const val = pipe.transform(void(0), mapping);
const val = pipe.transform(void(0) as any, mapping);
expect(val).toEqual('');
});

View File

@ -51,8 +51,8 @@ export function main() {
describe('transform', () => {
it('should return correct value for numbers', () => {
expect(normalize(pipe.transform(1.23))).toEqual('123%');
expect(normalize(pipe.transform(1.2, '.2'))).toEqual('120.00%');
expect(normalize(pipe.transform(1.23) !)).toEqual('123%');
expect(normalize(pipe.transform(1.2, '.2') !)).toEqual('120.00%');
});
it('should not support other objects',
@ -69,12 +69,12 @@ export function main() {
it('should return correct value for numbers', () => {
// In old Chrome, default formatiing for USD is different
if (browserDetection.isOldChrome) {
expect(normalize(pipe.transform(123))).toEqual('USD123');
expect(normalize(pipe.transform(123) !)).toEqual('USD123');
} else {
expect(normalize(pipe.transform(123))).toEqual('USD123.00');
expect(normalize(pipe.transform(123) !)).toEqual('USD123.00');
}
expect(normalize(pipe.transform(12, 'EUR', false, '.1'))).toEqual('EUR12.0');
expect(normalize(pipe.transform(5.1234, 'USD', false, '.0-3'))).toEqual('USD5.123');
expect(normalize(pipe.transform(12, 'EUR', false, '.1') !)).toEqual('EUR12.0');
expect(normalize(pipe.transform(5.1234, 'USD', false, '.0-3') !)).toEqual('USD5.123');
});
it('should not support other objects',

View File

@ -25,7 +25,7 @@ export class SpyLocation implements Location {
/** @internal */
_baseHref: string = '';
/** @internal */
_platformStrategy: LocationStrategy = null;
_platformStrategy: LocationStrategy = null !;
setInitialPath(url: string) { this._history[this._historyIndex].path = url; }
@ -106,12 +106,12 @@ export class SpyLocation implements Location {
}
subscribe(
onNext: (value: any) => void, onThrow: (error: any) => void = null,
onReturn: () => void = null): Object {
onNext: (value: any) => void, onThrow?: ((error: any) => void)|null,
onReturn?: (() => void)|null): Object {
return this._subject.subscribe({next: onNext, error: onThrow, complete: onReturn});
}
normalize(url: string): string { return null; }
normalize(url: string): string { return null !; }
}
class LocationState {

View File

@ -4,6 +4,9 @@
"declaration": true,
"stripInternal": true,
"experimentalDecorators": true,
"strictNullChecks": true,
"noImplicitAny": true,
"noFallthroughCasesInSwitch": true,
"module": "es2015",
"moduleResolution": "node",
"outDir": "../../dist/packages/common",

View File

@ -5,9 +5,10 @@ export declare const APP_BASE_HREF: InjectionToken<string>;
export declare class AsyncPipe implements OnDestroy, PipeTransform {
constructor(_ref: ChangeDetectorRef);
ngOnDestroy(): void;
transform<T>(obj: EventEmitter<T>): T | null;
transform<T>(obj: Promise<T>): T | null;
transform<T>(obj: Observable<T>): T | null;
transform<T>(obj: undefined): undefined;
transform<T>(obj: null): null;
}
/** @stable */
@ -17,19 +18,19 @@ export declare class CommonModule {
/** @stable */
export declare class CurrencyPipe implements PipeTransform {
constructor(_locale: string);
transform(value: any, currencyCode?: string, symbolDisplay?: boolean, digits?: string): string;
transform(value: any, currencyCode?: string, symbolDisplay?: boolean, digits?: string): string | null;
}
/** @stable */
export declare class DatePipe implements PipeTransform {
constructor(_locale: string);
transform(value: any, pattern?: string): string;
transform(value: any, pattern?: string): string | null;
}
/** @stable */
export declare class DecimalPipe implements PipeTransform {
constructor(_locale: string);
transform(value: any, digits?: string): string;
transform(value: any, digits?: string): string | null;
}
/** @stable */
@ -55,7 +56,7 @@ export declare class I18nPluralPipe implements PipeTransform {
/** @experimental */
export declare class I18nSelectPipe implements PipeTransform {
transform(value: string, mapping: {
transform(value: string | null | undefined, mapping: {
[key: string]: string;
}): string;
}
@ -88,7 +89,7 @@ export declare class Location {
path(includeHash?: boolean): string;
prepareExternalUrl(url: string): string;
replaceState(path: string, query?: string): void;
subscribe(onNext: (value: PopStateEvent) => void, onThrow?: (exception: any) => void, onReturn?: () => void): Object;
subscribe(onNext: (value: PopStateEvent) => void, onThrow?: ((exception: any) => void) | null, onReturn?: (() => void) | null): Object;
static joinWithSlash(start: string, end: string): string;
static normalizeQueryParams(params: string): string;
static stripTrailingSlash(url: string): string;
@ -261,14 +262,14 @@ export declare class PathLocationStrategy extends LocationStrategy {
/** @stable */
export declare class PercentPipe implements PipeTransform {
constructor(_locale: string);
transform(value: any, digits?: string): string;
transform(value: any, digits?: string): string | null;
}
/** @stable */
export declare abstract class PlatformLocation {
readonly hash: string;
readonly pathname: string;
readonly search: string;
readonly abstract hash: string;
readonly abstract pathname: string;
readonly abstract search: string;
abstract back(): void;
abstract forward(): void;
abstract getBaseHrefFromDOM(): string;

View File

@ -31,5 +31,5 @@ export declare class SpyLocation implements Location {
setInitialPath(url: string): void;
simulateHashChange(pathname: string): void;
simulateUrlPop(pathname: string): void;
subscribe(onNext: (value: any) => void, onThrow?: (error: any) => void, onReturn?: () => void): Object;
subscribe(onNext: (value: any) => void, onThrow?: ((error: any) => void) | null, onReturn?: (() => void) | null): Object;
}