diff --git a/projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts b/projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts index 22c57669a..0d5d874fd 100644 --- a/projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts +++ b/projects/core/src/lib/classes/mask-model/utils/calibrate-value-by-mask.ts @@ -1,4 +1,5 @@ import type {ElementState, MaskitoMaskExpression} from '../../../types'; +import {isArray} from '../../../utils'; import {guessValidValueByPattern} from './guess-valid-value-by-pattern'; import {guessValidValueByRegExp} from './guess-valid-value-by-reg-exp'; import {validateValueWithMask} from './validate-value-with-mask'; @@ -12,12 +13,12 @@ export function calibrateValueByMask( return elementState; } - const {value, selection} = Array.isArray(mask) + const {value, selection} = isArray(mask) ? guessValidValueByPattern(elementState, mask, initialElementState) : guessValidValueByRegExp(elementState, mask); return { selection, - value: Array.isArray(mask) ? value.slice(0, mask.length) : value, + value: isArray(mask) ? value.slice(0, mask.length) : value, }; } diff --git a/projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts b/projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts index 08da8c396..d00094cf5 100644 --- a/projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts +++ b/projects/core/src/lib/classes/mask-model/utils/get-leading-fixed-characters.ts @@ -2,7 +2,7 @@ import type {ElementState} from '../../../types'; import {isFixedCharacter} from './is-fixed-character'; export function getLeadingFixedCharacters( - mask: Array, + mask: ReadonlyArray, validatedValuePart: string, newCharacter: string, initialElementState: ElementState | null, diff --git a/projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts b/projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts index d708e3533..979f05efd 100644 --- a/projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts +++ b/projects/core/src/lib/classes/mask-model/utils/guess-valid-value-by-pattern.ts @@ -5,7 +5,7 @@ import {validateValueWithMask} from './validate-value-with-mask'; export function guessValidValueByPattern( elementState: ElementState, - mask: Array, + mask: ReadonlyArray, initialElementState: ElementState | null, ): ElementState { let maskedFrom: number | null = null; diff --git a/projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts b/projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts index 4b838d9f2..a8c274b0f 100644 --- a/projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts +++ b/projects/core/src/lib/classes/mask-model/utils/remove-fixed-mask-characters.ts @@ -1,11 +1,12 @@ import type {ElementState, MaskitoMaskExpression} from '../../../types'; +import {isArray} from '../../../utils'; import {isFixedCharacter} from './is-fixed-character'; export function removeFixedMaskCharacters( initialElementState: ElementState, mask: MaskitoMaskExpression, ): ElementState { - if (!Array.isArray(mask)) { + if (!isArray(mask)) { return initialElementState; } diff --git a/projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts b/projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts index 46a88bdf6..e34203336 100644 --- a/projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts +++ b/projects/core/src/lib/classes/mask-model/utils/validate-value-with-mask.ts @@ -1,11 +1,12 @@ import type {MaskitoMaskExpression} from '../../../types'; +import {isArray} from '../../../utils'; import {isFixedCharacter} from './is-fixed-character'; export function validateValueWithMask( value: string, maskExpression: MaskitoMaskExpression, ): boolean { - if (Array.isArray(maskExpression)) { + if (isArray(maskExpression)) { return ( value.length === maskExpression.length && Array.from(value).every((char, i) => { diff --git a/projects/core/src/lib/types/mask.ts b/projects/core/src/lib/types/mask.ts index 4a9c74a23..52c60c923 100644 --- a/projects/core/src/lib/types/mask.ts +++ b/projects/core/src/lib/types/mask.ts @@ -1,6 +1,6 @@ import type {ElementState} from './element-state'; -export type MaskitoMaskExpression = Array | RegExp; +export type MaskitoMaskExpression = ReadonlyArray | RegExp; export type MaskitoMask = | MaskitoMaskExpression diff --git a/projects/core/src/lib/utils/index.ts b/projects/core/src/lib/utils/index.ts index bcc76c995..5118a7bbc 100644 --- a/projects/core/src/lib/utils/index.ts +++ b/projects/core/src/lib/utils/index.ts @@ -8,5 +8,6 @@ export * from './element-states-equality'; export * from './get-line-selection'; export * from './get-not-empty-selection'; export * from './get-word-selection'; +export * from './is-array'; export * from './pipe'; export * from './transform'; diff --git a/projects/core/src/lib/utils/is-array.ts b/projects/core/src/lib/utils/is-array.ts new file mode 100644 index 000000000..ea94730e2 --- /dev/null +++ b/projects/core/src/lib/utils/is-array.ts @@ -0,0 +1,7 @@ +/** + * @internal + */ +export function isArray(value: any): value is readonly unknown[] { + // See (Jul 7, 2017): https://github.com/microsoft/TypeScript/issues/17002 + return Array.isArray(value); +} diff --git a/projects/demo-integrations/src/tests/kit/date-time/date-time-date-time-separator.cy.ts b/projects/demo-integrations/src/tests/kit/date-time/date-time-date-time-separator.cy.ts index 51290be15..84ff3649e 100644 --- a/projects/demo-integrations/src/tests/kit/date-time/date-time-date-time-separator.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date-time/date-time-date-time-separator.cy.ts @@ -5,7 +5,7 @@ describe('DateTime | dateTimeSeparator', () => { const dateTimeSeparators = [':', ';_', '_-_', '_at_']; dateTimeSeparators.forEach((dateTimeSeparator) => { - const testCases: Array<{ + const testCases: ReadonlyArray<{ typedDigits: string; formattedDate: string; formattedValue: string; diff --git a/projects/demo-integrations/src/tests/kit/number/number-minus-sign.cy.ts b/projects/demo-integrations/src/tests/kit/number/number-minus-sign.cy.ts index 11cff901d..30876c3ec 100644 --- a/projects/demo-integrations/src/tests/kit/number/number-minus-sign.cy.ts +++ b/projects/demo-integrations/src/tests/kit/number/number-minus-sign.cy.ts @@ -9,7 +9,7 @@ import { import {openNumberPage} from './utils'; describe('Number | minus sign', () => { - const pseudoMinuses: Array<{value: string; name: string}> = [ + const pseudoMinuses: ReadonlyArray<{value: string; name: string}> = [ {value: CHAR_HYPHEN, name: 'hyphen'}, {value: CHAR_EN_DASH, name: 'en-dash'}, {value: CHAR_EM_DASH, name: 'em-dash'}, @@ -18,7 +18,7 @@ describe('Number | minus sign', () => { ]; describe('can use hyphen, all kind of dashes and minus interchangeably', () => { - const minuses: Array<{value: string; name: string}> = [ + const minuses: ReadonlyArray<{value: string; name: string}> = [ { value: CHAR_HYPHEN, name: 'hyphen', diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index fcb74d1ed..9d6d99e69 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -80,16 +80,13 @@ export default class DateRangeMaskDocComponent implements GeneratorOptions { '2025-05-10', ] as const; - protected readonly minLengthOptions: Array>> = [ - {day: 3}, - {day: 15}, - ]; - - protected readonly maxLengthOptions: Array>> = [ - {day: 5}, - {month: 1}, - {year: 1}, - ]; + protected readonly minLengthOptions: ReadonlyArray< + Partial> + > = [{day: 3}, {day: 15}]; + + protected readonly maxLengthOptions: ReadonlyArray< + Partial> + > = [{day: 5}, {month: 1}, {year: 1}]; protected minStr: string = this.minMaxOptions[0]; protected maxStr: string = this.minMaxOptions[1]; diff --git a/projects/kit/src/lib/masks/date-time/tests/date-time-separator.spec.ts b/projects/kit/src/lib/masks/date-time/tests/date-time-separator.spec.ts index 21d2627d2..9f33bc6dc 100644 --- a/projects/kit/src/lib/masks/date-time/tests/date-time-separator.spec.ts +++ b/projects/kit/src/lib/masks/date-time/tests/date-time-separator.spec.ts @@ -9,7 +9,7 @@ describe('DateTime | dateTimeSeparator', () => { let options = MASKITO_DEFAULT_OPTIONS; dateTimeSeparators.forEach((dateTimeSeparator) => { - const testCases: Array<{ + const testCases: ReadonlyArray<{ typedDigits: string; formattedValue: string; timeMode: MaskitoTimeMode; diff --git a/projects/kit/src/lib/masks/time/utils/tests/parse-time.spec.ts b/projects/kit/src/lib/masks/time/utils/tests/parse-time.spec.ts index fde43978a..15e4813ed 100644 --- a/projects/kit/src/lib/masks/time/utils/tests/parse-time.spec.ts +++ b/projects/kit/src/lib/masks/time/utils/tests/parse-time.spec.ts @@ -3,131 +3,133 @@ import type {MaskitoTimeMode} from '@maskito/kit'; import {maskitoParseTime} from '@maskito/kit'; describe('maskitoParseTime', () => { - const testCases = new Map>([ + const testCases = new Map>( [ - 'HH:MM:SS.MSS', [ - {text: '', ms: 0}, - {text: '00:00:00.000', ms: 0}, + 'HH:MM:SS.MSS', + [ + {text: '', ms: 0}, + {text: '00:00:00.000', ms: 0}, - {text: '1', ms: 36000000}, - {text: '10', ms: 36000000}, - {text: '12', ms: 43200000}, - {text: '12:', ms: 43200000}, - {text: '12:3', ms: 45000000}, - {text: '12:30', ms: 45000000}, - {text: '12:34', ms: 45240000}, - {text: '12:34:', ms: 45240000}, - {text: '12:34:5', ms: 45290000}, - {text: '12:34:50', ms: 45290000}, - {text: '12:34:56', ms: 45296000}, - {text: '12:34:56.', ms: 45296000}, - {text: '12:34:56.7', ms: 45296700}, - {text: '12:34:56.70', ms: 45296700}, - {text: '12:34:56.700', ms: 45296700}, - {text: '12:34:56.78', ms: 45296780}, - {text: '12:34:56.780', ms: 45296780}, - {text: '12:34:56.789', ms: 45296789}, + {text: '1', ms: 36000000}, + {text: '10', ms: 36000000}, + {text: '12', ms: 43200000}, + {text: '12:', ms: 43200000}, + {text: '12:3', ms: 45000000}, + {text: '12:30', ms: 45000000}, + {text: '12:34', ms: 45240000}, + {text: '12:34:', ms: 45240000}, + {text: '12:34:5', ms: 45290000}, + {text: '12:34:50', ms: 45290000}, + {text: '12:34:56', ms: 45296000}, + {text: '12:34:56.', ms: 45296000}, + {text: '12:34:56.7', ms: 45296700}, + {text: '12:34:56.70', ms: 45296700}, + {text: '12:34:56.700', ms: 45296700}, + {text: '12:34:56.78', ms: 45296780}, + {text: '12:34:56.780', ms: 45296780}, + {text: '12:34:56.789', ms: 45296789}, - {text: '23:59:59.999', ms: 86399999}, + {text: '23:59:59.999', ms: 86399999}, + ], ], - ], - [ - 'HH:MM:SS', [ - {text: '', ms: 0}, - {text: '00:00:00', ms: 0}, + 'HH:MM:SS', + [ + {text: '', ms: 0}, + {text: '00:00:00', ms: 0}, - {text: '1', ms: 36000000}, - {text: '10', ms: 36000000}, - {text: '12', ms: 43200000}, - {text: '12:', ms: 43200000}, - {text: '12:3', ms: 45000000}, - {text: '12:30', ms: 45000000}, - {text: '12:34', ms: 45240000}, - {text: '12:34:', ms: 45240000}, - {text: '12:34:5', ms: 45290000}, - {text: '12:34:50', ms: 45290000}, - {text: '12:34:56', ms: 45296000}, + {text: '1', ms: 36000000}, + {text: '10', ms: 36000000}, + {text: '12', ms: 43200000}, + {text: '12:', ms: 43200000}, + {text: '12:3', ms: 45000000}, + {text: '12:30', ms: 45000000}, + {text: '12:34', ms: 45240000}, + {text: '12:34:', ms: 45240000}, + {text: '12:34:5', ms: 45290000}, + {text: '12:34:50', ms: 45290000}, + {text: '12:34:56', ms: 45296000}, - {text: '23:59:59', ms: 86399000}, + {text: '23:59:59', ms: 86399000}, + ], ], - ], - [ - 'HH:MM', [ - {text: '', ms: 0}, - {text: '00:00', ms: 0}, + 'HH:MM', + [ + {text: '', ms: 0}, + {text: '00:00', ms: 0}, - {text: '1', ms: 36000000}, - {text: '10', ms: 36000000}, - {text: '12', ms: 43200000}, - {text: '12:', ms: 43200000}, - {text: '12:3', ms: 45000000}, - {text: '12:30', ms: 45000000}, - {text: '12:34', ms: 45240000}, + {text: '1', ms: 36000000}, + {text: '10', ms: 36000000}, + {text: '12', ms: 43200000}, + {text: '12:', ms: 43200000}, + {text: '12:3', ms: 45000000}, + {text: '12:30', ms: 45000000}, + {text: '12:34', ms: 45240000}, - {text: '23:59', ms: 86340000}, + {text: '23:59', ms: 86340000}, + ], ], - ], - [ - 'HH', [ - {text: '', ms: 0}, - {text: '00', ms: 0}, + 'HH', + [ + {text: '', ms: 0}, + {text: '00', ms: 0}, - {text: '1', ms: 36000000}, - {text: '10', ms: 36000000}, - {text: '12', ms: 43200000}, + {text: '1', ms: 36000000}, + {text: '10', ms: 36000000}, + {text: '12', ms: 43200000}, - {text: '23', ms: 82800000}, + {text: '23', ms: 82800000}, + ], ], - ], - [ - 'MM:SS.MSS', [ - {text: '', ms: 0}, - {text: '00:00.000', ms: 0}, + 'MM:SS.MSS', + [ + {text: '', ms: 0}, + {text: '00:00.000', ms: 0}, - {text: '1', ms: 600000}, - {text: '10', ms: 600000}, - {text: '12', ms: 720000}, - {text: '12.', ms: 720000}, - {text: '12:3', ms: 750000}, - {text: '12:30', ms: 750000}, - {text: '12:34', ms: 754000}, - {text: '12:34.', ms: 754000}, - {text: '12:34.5', ms: 754500}, - {text: '12:34.50', ms: 754500}, - {text: '12:34.500', ms: 754500}, - {text: '12:34.56', ms: 754560}, - {text: '12:34.560', ms: 754560}, - {text: '12:34.567', ms: 754567}, + {text: '1', ms: 600000}, + {text: '10', ms: 600000}, + {text: '12', ms: 720000}, + {text: '12.', ms: 720000}, + {text: '12:3', ms: 750000}, + {text: '12:30', ms: 750000}, + {text: '12:34', ms: 754000}, + {text: '12:34.', ms: 754000}, + {text: '12:34.5', ms: 754500}, + {text: '12:34.50', ms: 754500}, + {text: '12:34.500', ms: 754500}, + {text: '12:34.56', ms: 754560}, + {text: '12:34.560', ms: 754560}, + {text: '12:34.567', ms: 754567}, - {text: '59:59.999', ms: 3599999}, + {text: '59:59.999', ms: 3599999}, + ], ], - ], - [ - 'SS.MSS', [ - {text: '', ms: 0}, - {text: '00.000', ms: 0}, + 'SS.MSS', + [ + {text: '', ms: 0}, + {text: '00.000', ms: 0}, - {text: '1', ms: 10000}, - {text: '10', ms: 10000}, - {text: '12', ms: 12000}, - {text: '12.', ms: 12000}, - {text: '12.3', ms: 12300}, - {text: '12.30', ms: 12300}, - {text: '12.300', ms: 12300}, - {text: '12.34', ms: 12340}, - {text: '12.340', ms: 12340}, - {text: '12.345', ms: 12345}, + {text: '1', ms: 10000}, + {text: '10', ms: 10000}, + {text: '12', ms: 12000}, + {text: '12.', ms: 12000}, + {text: '12.3', ms: 12300}, + {text: '12.30', ms: 12300}, + {text: '12.300', ms: 12300}, + {text: '12.34', ms: 12340}, + {text: '12.340', ms: 12340}, + {text: '12.345', ms: 12345}, - {text: '59.999', ms: 59999}, + {text: '59.999', ms: 59999}, + ], ], ], - ]); + ); testCases.forEach((cases, mode) => { describe(`mode ${mode}`, () => { diff --git a/projects/kit/src/lib/masks/time/utils/tests/stringify-time.spec.ts b/projects/kit/src/lib/masks/time/utils/tests/stringify-time.spec.ts index 2a917cd7c..12b1c3686 100644 --- a/projects/kit/src/lib/masks/time/utils/tests/stringify-time.spec.ts +++ b/projects/kit/src/lib/masks/time/utils/tests/stringify-time.spec.ts @@ -3,63 +3,65 @@ import type {MaskitoTimeMode} from '@maskito/kit'; import {maskitoStringifyTime} from '@maskito/kit'; describe('maskitoStringifyTime', () => { - const testCases = new Map>([ + const testCases = new Map>( [ - 'HH:MM:SS.MSS', [ - {ms: 0, text: '00:00:00.000'}, - {ms: 3661001, text: '01:01:01.001'}, - {ms: 45296789, text: '12:34:56.789'}, - {ms: 86399999, text: '23:59:59.999'}, + 'HH:MM:SS.MSS', + [ + {ms: 0, text: '00:00:00.000'}, + {ms: 3661001, text: '01:01:01.001'}, + {ms: 45296789, text: '12:34:56.789'}, + {ms: 86399999, text: '23:59:59.999'}, + ], ], - ], - [ - 'HH:MM:SS', [ - {ms: 0, text: '00:00:00'}, - {ms: 3661000, text: '01:01:01'}, - {ms: 10920000, text: '03:02:00'}, - {ms: 45296000, text: '12:34:56'}, - {ms: 86399000, text: '23:59:59'}, + 'HH:MM:SS', + [ + {ms: 0, text: '00:00:00'}, + {ms: 3661000, text: '01:01:01'}, + {ms: 10920000, text: '03:02:00'}, + {ms: 45296000, text: '12:34:56'}, + {ms: 86399000, text: '23:59:59'}, + ], ], - ], - [ - 'HH:MM', [ - {ms: 0, text: '00:00'}, - {ms: 3660000, text: '01:01'}, - {ms: 45240000, text: '12:34'}, - {ms: 86340000, text: '23:59'}, + 'HH:MM', + [ + {ms: 0, text: '00:00'}, + {ms: 3660000, text: '01:01'}, + {ms: 45240000, text: '12:34'}, + {ms: 86340000, text: '23:59'}, + ], ], - ], - [ - 'HH', [ - {ms: 0, text: '00'}, - {ms: 3600000, text: '01'}, - {ms: 43200000, text: '12'}, - {ms: 82800000, text: '23'}, + 'HH', + [ + {ms: 0, text: '00'}, + {ms: 3600000, text: '01'}, + {ms: 43200000, text: '12'}, + {ms: 82800000, text: '23'}, + ], ], - ], - [ - 'MM:SS.MSS', [ - {ms: 0, text: '00:00.000'}, - {ms: 61001, text: '01:01.001'}, - {ms: 754567, text: '12:34.567'}, - {ms: 3599999, text: '59:59.999'}, + 'MM:SS.MSS', + [ + {ms: 0, text: '00:00.000'}, + {ms: 61001, text: '01:01.001'}, + {ms: 754567, text: '12:34.567'}, + {ms: 3599999, text: '59:59.999'}, + ], ], - ], - [ - 'SS.MSS', [ - {ms: 0, text: '00.000'}, - {ms: 1001, text: '01.001'}, - {ms: 12345, text: '12.345'}, - {ms: 59999, text: '59.999'}, + 'SS.MSS', + [ + {ms: 0, text: '00.000'}, + {ms: 1001, text: '01.001'}, + {ms: 12345, text: '12.345'}, + {ms: 59999, text: '59.999'}, + ], ], ], - ]); + ); testCases.forEach((cases, mode) => { describe(`mode ${mode}`, () => { diff --git a/projects/kit/src/lib/processors/date-segments-zero-padding-postprocessor.ts b/projects/kit/src/lib/processors/date-segments-zero-padding-postprocessor.ts index 7c70bf00e..8b0754c69 100644 --- a/projects/kit/src/lib/processors/date-segments-zero-padding-postprocessor.ts +++ b/projects/kit/src/lib/processors/date-segments-zero-padding-postprocessor.ts @@ -23,7 +23,7 @@ export function createDateSegmentsZeroPaddingPostprocessor({ dateStrings.forEach((dateString) => { const parsedDate = parseDateString(dateString, dateModeTemplate); - const dateSegments = Object.entries(parsedDate) as Array< + const dateSegments = Object.entries(parsedDate) as ReadonlyArray< [keyof MaskitoDateSegments, string] >; diff --git a/projects/kit/src/lib/processors/invalid-time-segment-insertion-preprocessor.ts b/projects/kit/src/lib/processors/invalid-time-segment-insertion-preprocessor.ts index a9a656e41..1eb3712c4 100644 --- a/projects/kit/src/lib/processors/invalid-time-segment-insertion-preprocessor.ts +++ b/projects/kit/src/lib/processors/invalid-time-segment-insertion-preprocessor.ts @@ -41,7 +41,7 @@ export function createInvalidTimeSegmentInsertionPreprocessor({ const {timeString, restValue = ''} = parseValue(newPossibleValue); const timeSegments = Object.entries( parseTimeString(timeString, timeMode), - ) as Array<[keyof MaskitoTimeSegments, string]>; + ) as ReadonlyArray<[keyof MaskitoTimeSegments, string]>; let offset = restValue.length; diff --git a/projects/kit/src/lib/utils/date/validate-date-string.ts b/projects/kit/src/lib/utils/date/validate-date-string.ts index 2c3f7f8e8..1903e9201 100644 --- a/projects/kit/src/lib/utils/date/validate-date-string.ts +++ b/projects/kit/src/lib/utils/date/validate-date-string.ts @@ -18,7 +18,7 @@ export function validateDateString({ selection: [number, number]; }): {validatedDateString: string; updatedSelection: [number, number]} { const parsedDate = parseDateString(dateString, dateModeTemplate); - const dateSegments = Object.entries(parsedDate) as Array< + const dateSegments = Object.entries(parsedDate) as ReadonlyArray< [keyof MaskitoDateSegments, string] >; const validatedDateSegments: Partial = {}; diff --git a/projects/kit/src/lib/utils/time/enrich-time-segments-with-zeroes.ts b/projects/kit/src/lib/utils/time/enrich-time-segments-with-zeroes.ts index c3013bfd8..8c40b04ff 100644 --- a/projects/kit/src/lib/utils/time/enrich-time-segments-with-zeroes.ts +++ b/projects/kit/src/lib/utils/time/enrich-time-segments-with-zeroes.ts @@ -27,7 +27,7 @@ export function enrichTimeSegmentsWithZeroes( ): {value: string; selection: readonly [number, number]} { const [from, to] = selection; const parsedTime = parseTimeString(value, mode); - const possibleTimeSegments = Object.entries(parsedTime) as Array< + const possibleTimeSegments = Object.entries(parsedTime) as ReadonlyArray< [keyof MaskitoTimeSegments, string] >;