Skip to content

Commit 85711f6

Browse files
committed
feat(locale): 🎸 improve strict mode types for pipes
Keep null and undefined intact and provide overloads with null and undefined values for all pipes. BREAKING CHANGE: 🧨 Pipes return null or undefined instead of an empty string if the input is null or undefined ✅ Closes: #755
1 parent 99ce1c1 commit 85711f6

8 files changed

+222
-34
lines changed

libs/transloco-locale/src/lib/pipes/transloco-currency.pipe.ts

+42-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212

1313
import { BaseLocalePipe } from './base-locale.pipe';
1414

15+
type CurrencyDisplayType = 'code' | 'symbol' | 'narrowSymbol' | 'name';
16+
1517
@Pipe({
1618
name: 'translocoCurrency',
1719
pure: false,
@@ -35,14 +37,51 @@ export class TranslocoCurrencyPipe
3537
* 1000000 | translocoCurrency: 'narrowSymbol' : {minimumFractionDigits: 0 } : CAD // $1,000,000
3638
*
3739
*/
40+
// overloads for strict mode
3841
transform(
3942
value: number | string,
40-
display: 'code' | 'symbol' | 'narrowSymbol' | 'name' = 'symbol',
43+
display?: CurrencyDisplayType,
44+
numberFormatOptions?: NumberFormatOptions,
45+
currencyCode?: Currency,
46+
locale?: Locale
47+
): string;
48+
transform(
49+
value: null | undefined,
50+
display?: CurrencyDisplayType,
51+
numberFormatOptions?: NumberFormatOptions,
52+
currencyCode?: Currency,
53+
locale?: Locale
54+
): null | undefined;
55+
transform(
56+
value: number | string | null,
57+
display?: CurrencyDisplayType,
58+
numberFormatOptions?: NumberFormatOptions,
59+
currencyCode?: Currency,
60+
locale?: Locale
61+
): string | null;
62+
transform(
63+
value: number | string | undefined,
64+
display?: CurrencyDisplayType,
65+
numberFormatOptions?: NumberFormatOptions,
66+
currencyCode?: Currency,
67+
locale?: Locale
68+
): string | undefined;
69+
transform(
70+
value: number | string | null | undefined,
71+
display?: CurrencyDisplayType,
72+
numberFormatOptions?: NumberFormatOptions,
73+
currencyCode?: Currency,
74+
locale?: Locale
75+
): string | null | undefined;
76+
77+
transform(
78+
value?: number | string | null,
79+
display: CurrencyDisplayType = 'symbol',
4180
numberFormatOptions: NumberFormatOptions = {},
4281
currencyCode?: Currency,
4382
locale?: Locale
44-
): string {
45-
if (isNil(value)) return '';
83+
): string | null | undefined {
84+
if (isNil(value)) return value;
4685
locale = this.getLocale(locale);
4786

4887
const options = {

libs/transloco-locale/src/lib/pipes/transloco-date.pipe.ts

+33-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,39 @@ export class TranslocoDatePipe extends BaseLocalePipe implements PipeTransform {
3434
* 1 | translocoDate: { dateStyle: 'medium' } // Jan 1, 1970
3535
* '2019-02-08' | translocoDate: { dateStyle: 'medium' } // Feb 8, 2019
3636
*/
37-
transform(date: ValidDate, options: DateFormatOptions = {}, locale?: Locale) {
38-
if (isNil(date)) return '';
37+
// overloads for strict mode
38+
transform(
39+
date: ValidDate,
40+
options?: DateFormatOptions,
41+
locale?: Locale
42+
): string;
43+
transform(
44+
date: null | undefined,
45+
options?: DateFormatOptions,
46+
locale?: Locale
47+
): null | undefined;
48+
transform(
49+
date: ValidDate | null,
50+
options?: DateFormatOptions,
51+
locale?: Locale
52+
): string | null;
53+
transform(
54+
date: ValidDate | undefined,
55+
options?: DateFormatOptions,
56+
locale?: Locale
57+
): string | undefined;
58+
transform(
59+
date: ValidDate | null | undefined,
60+
options?: DateFormatOptions,
61+
locale?: Locale
62+
): string | null | undefined;
63+
64+
transform(
65+
date: ValidDate | null | undefined,
66+
options: DateFormatOptions = {},
67+
locale?: Locale
68+
): string | null | undefined {
69+
if (isNil(date)) return date;
3970
locale = this.getLocale(locale);
4071

4172
return this.localeService.localizeDate(date, locale, {

libs/transloco-locale/src/lib/pipes/transloco-decimal.pipe.ts

+30-3
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,39 @@ export class TranslocoDecimalPipe
3131
* 1234567890 | translocoDecimal: {useGrouping: false}: en-US // 1234567890
3232
*
3333
*/
34+
// overloads for strict mode
3435
transform(
35-
value: string | number,
36+
value: number | string,
37+
numberFormatOptions?: NumberFormatOptions,
38+
locale?: Locale
39+
): string;
40+
transform(
41+
value: null | undefined,
42+
numberFormatOptions?: NumberFormatOptions,
43+
locale?: Locale
44+
): null | undefined;
45+
transform(
46+
value: number | string | null,
47+
numberFormatOptions?: NumberFormatOptions,
48+
locale?: Locale
49+
): string | null;
50+
transform(
51+
value: number | string | undefined,
52+
numberFormatOptions?: NumberFormatOptions,
53+
locale?: Locale
54+
): string | undefined;
55+
transform(
56+
value: number | string | null | undefined,
57+
numberFormatOptions?: NumberFormatOptions,
58+
locale?: Locale
59+
): string | null | undefined;
60+
61+
transform(
62+
value?: string | number | null,
3663
numberFormatOptions: NumberFormatOptions = {},
3764
locale?: Locale
38-
): string {
39-
if (isNil(value)) return '';
65+
): string | null | undefined {
66+
if (isNil(value)) return value;
4067
locale = this.getLocale(locale);
4168

4269
const options = {

libs/transloco-locale/src/lib/pipes/transloco-percent.pipe.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,39 @@ export class TranslocoPercentPipe
3131
* "1" | translocoPercent : {} : en-US // 100%
3232
*
3333
*/
34+
// overloads for strict mode
3435
transform(
3536
value: number | string,
37+
numberFormatOptions?: NumberFormatOptions,
38+
locale?: Locale
39+
): string;
40+
transform(
41+
value: null | undefined,
42+
numberFormatOptions?: NumberFormatOptions,
43+
locale?: Locale
44+
): null | undefined;
45+
transform(
46+
value: number | string | null,
47+
numberFormatOptions?: NumberFormatOptions,
48+
locale?: Locale
49+
): string | null;
50+
transform(
51+
value: number | string | undefined,
52+
numberFormatOptions?: NumberFormatOptions,
53+
locale?: Locale
54+
): string | undefined;
55+
transform(
56+
value: number | string | null | undefined,
57+
numberFormatOptions?: NumberFormatOptions,
58+
locale?: Locale
59+
): string | null | undefined;
60+
61+
transform(
62+
value?: number | string | null,
3663
numberFormatOptions: NumberFormatOptions = {},
3764
locale?: Locale
38-
): string {
39-
if (isNil(value)) return '';
65+
): string | null | undefined {
66+
if (isNil(value)) return value;
4067
locale = this.getLocale(locale);
4168

4269
const options = {

libs/transloco-locale/src/lib/tests/pipes/transloco-currency.pipe.spec.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { SpectatorPipe } from '@ngneat/spectator';
2+
import { ChangeDetectorRef } from '@angular/core';
3+
import { TestBed } from '@angular/core/testing';
4+
import { Mock } from 'ts-mocks';
25

36
import { TranslocoCurrencyPipe } from '../../pipes/transloco-currency.pipe';
47
import { LOCALE_CONFIG_MOCK, provideTranslocoServiceMock } from '../mocks';
@@ -60,17 +63,30 @@ describe('TranslocoCurrencyPipe', () => {
6063
});
6164

6265
describe('None transformable values', () => {
66+
let pipe: TranslocoCurrencyPipe;
67+
let cdrMock: ChangeDetectorRef;
68+
69+
beforeEach(() => {
70+
cdrMock = new Mock<ChangeDetectorRef>({
71+
markForCheck: () => {},
72+
}).Object;
73+
74+
TestBed.configureTestingModule({
75+
providers: [{ provide: ChangeDetectorRef, useValue: cdrMock }],
76+
});
77+
pipe = TestBed.runInInjectionContext(() => new TranslocoCurrencyPipe());
78+
});
6379
it('should handle null', () => {
64-
spectator = pipeFactory(`{{ null | translocoCurrency }}`);
65-
expect(spectator.element).toHaveText('');
80+
expect(pipe.transform(null)).toBeNull();
81+
});
82+
it('should handle undefined', () => {
83+
expect(pipe.transform(undefined)).toBeUndefined();
6684
});
6785
it('should handle {}', () => {
68-
spectator = pipeFactory(`{{ {} | translocoCurrency }}`);
69-
expect(spectator.element).toHaveText('');
86+
expect(pipe.transform({} as any)).toBe('');
7087
});
7188
it('should handle none number string', () => {
72-
spectator = pipeFactory(`{{ 'none number string' | translocoCurrency }}`);
73-
expect(spectator.element).toHaveText('');
89+
expect(pipe.transform('none number string')).toBe('');
7490
});
7591
});
7692

libs/transloco-locale/src/lib/tests/pipes/transloco-date.pipe.spec.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { SpectatorPipe } from '@ngneat/spectator';
2+
import { ChangeDetectorRef } from '@angular/core';
3+
import { TestBed } from '@angular/core/testing';
4+
import { Mock } from 'ts-mocks';
25

36
import { TranslocoDatePipe } from '../../pipes';
47
import {
@@ -88,17 +91,30 @@ describe('TranslocoDatePipe', () => {
8891
});
8992

9093
describe('None date values', () => {
94+
let pipe: TranslocoDatePipe;
95+
let cdrMock: ChangeDetectorRef;
96+
97+
beforeEach(() => {
98+
cdrMock = new Mock<ChangeDetectorRef>({
99+
markForCheck: () => {},
100+
}).Object;
101+
102+
TestBed.configureTestingModule({
103+
providers: [{ provide: ChangeDetectorRef, useValue: cdrMock }],
104+
});
105+
pipe = TestBed.runInInjectionContext(() => new TranslocoDatePipe());
106+
});
91107
it('should handle null', () => {
92-
spectator = pipeFactory(`{{ null | translocoDate }}`);
93-
expect(spectator.element).toHaveText('');
108+
expect(pipe.transform(null)).toBeNull();
109+
});
110+
it('should handle undefined', () => {
111+
expect(pipe.transform(undefined)).toBeUndefined();
94112
});
95113
it('should handle {}', () => {
96-
spectator = pipeFactory(`{{ {} | translocoDate }}`);
97-
expect(spectator.element).toHaveText('');
114+
expect(pipe.transform({} as any)).toBe('');
98115
});
99116
it('should handle none number string', () => {
100-
spectator = pipeFactory(`{{ 'none number string' | translocoDate }}`);
101-
expect(spectator.element).toHaveText('');
117+
expect(pipe.transform('none number string')).toBe('');
102118
});
103119
});
104120

libs/transloco-locale/src/lib/tests/pipes/transloco-decimal.pipe.spec.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { SpectatorPipe } from '@ngneat/spectator';
2+
import { ChangeDetectorRef } from '@angular/core';
3+
import { TestBed } from '@angular/core/testing';
4+
import { Mock } from 'ts-mocks';
25

36
import { TranslocoDecimalPipe } from '../../pipes';
47
import {
@@ -66,17 +69,30 @@ describe('TranslocoDecimalPipe', () => {
6669
});
6770

6871
describe('None transformable values', () => {
72+
let pipe: TranslocoDecimalPipe;
73+
let cdrMock: ChangeDetectorRef;
74+
75+
beforeEach(() => {
76+
cdrMock = new Mock<ChangeDetectorRef>({
77+
markForCheck: () => {},
78+
}).Object;
79+
80+
TestBed.configureTestingModule({
81+
providers: [{ provide: ChangeDetectorRef, useValue: cdrMock }],
82+
});
83+
pipe = TestBed.runInInjectionContext(() => new TranslocoDecimalPipe());
84+
});
6985
it('should handle null', () => {
70-
spectator = pipeFactory(`{{ null | translocoDecimal }}`);
71-
expect(spectator.element).toHaveText('');
86+
expect(pipe.transform(null)).toBeNull();
87+
});
88+
it('should handle undefined', () => {
89+
expect(pipe.transform(undefined)).toBeUndefined();
7290
});
7391
it('should handle {}', () => {
74-
spectator = pipeFactory(`{{ {} | translocoDecimal }}`);
75-
expect(spectator.element).toHaveText('');
92+
expect(pipe.transform({} as any)).toBe('');
7693
});
7794
it('should handle none number string', () => {
78-
spectator = pipeFactory(`{{ 'none number string' | translocoDecimal }}`);
79-
expect(spectator.element).toHaveText('');
95+
expect(pipe.transform('none number string')).toBe('');
8096
});
8197
});
8298
});

libs/transloco-locale/src/lib/tests/pipes/transloco-percent.pipe.spec.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { SpectatorPipe } from '@ngneat/spectator';
2+
import { ChangeDetectorRef } from '@angular/core';
3+
import { TestBed } from '@angular/core/testing';
4+
import { Mock } from 'ts-mocks';
25

36
import { TranslocoPercentPipe } from '../../pipes';
47
import { LOCALE_CONFIG_MOCK, provideTranslocoLocaleConfigMock } from '../mocks';
@@ -31,17 +34,30 @@ describe('TranslocoPercentPipe', () => {
3134
});
3235

3336
describe('None transformable values', () => {
37+
let pipe: TranslocoPercentPipe;
38+
let cdrMock: ChangeDetectorRef;
39+
40+
beforeEach(() => {
41+
cdrMock = new Mock<ChangeDetectorRef>({
42+
markForCheck: () => {},
43+
}).Object;
44+
45+
TestBed.configureTestingModule({
46+
providers: [{ provide: ChangeDetectorRef, useValue: cdrMock }],
47+
});
48+
pipe = TestBed.runInInjectionContext(() => new TranslocoPercentPipe());
49+
});
3450
it('should handle null', () => {
35-
spectator = pipeFactory(getPipeTpl(null));
36-
expect(spectator.element).toHaveText('');
51+
expect(pipe.transform(null)).toBeNull();
52+
});
53+
it('should handle undefined', () => {
54+
expect(pipe.transform(undefined)).toBeUndefined();
3755
});
3856
it('should handle {}', () => {
39-
spectator = pipeFactory(getPipeTpl({}));
40-
expect(spectator.element).toHaveText('');
57+
expect(pipe.transform({} as any)).toBe('');
4158
});
4259
it('should handle none number string', () => {
43-
spectator = pipeFactory(getPipeTpl('none number string'));
44-
expect(spectator.element).toHaveText('');
60+
expect(pipe.transform('none number string')).toBe('');
4561
});
4662
});
4763

0 commit comments

Comments
 (0)