diff options
| author | ST-DDT <[email protected]> | 2023-11-14 17:11:26 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-11-14 16:11:26 +0000 |
| commit | 7e3c92e802614ae5e9f621d9e679dfd6f6d63cf1 (patch) | |
| tree | bb6813a857c0c42ba1049be5035fce7f45b99c46 /src | |
| parent | 36fc517d17591c8ea1d5135d9a93c7591e3d1f74 (diff) | |
| download | faker-7e3c92e802614ae5e9f621d9e679dfd6f6d63cf1.tar.xz faker-7e3c92e802614ae5e9f621d9e679dfd6f6d63cf1.zip | |
infra: enable strictNullChecks in tsconfig (#2435)
Diffstat (limited to 'src')
| -rw-r--r-- | src/definitions/date.ts | 3 | ||||
| -rw-r--r-- | src/definitions/definitions.ts | 2 | ||||
| -rw-r--r-- | src/locale-proxy.ts | 40 | ||||
| -rw-r--r-- | src/modules/airline/index.ts | 2 | ||||
| -rw-r--r-- | src/modules/color/index.ts | 37 | ||||
| -rw-r--r-- | src/modules/commerce/index.ts | 10 | ||||
| -rw-r--r-- | src/modules/date/index.ts | 51 | ||||
| -rw-r--r-- | src/modules/finance/index.ts | 22 | ||||
| -rw-r--r-- | src/modules/helpers/index.ts | 2 | ||||
| -rw-r--r-- | src/modules/helpers/unique.ts | 4 | ||||
| -rw-r--r-- | src/modules/internet/index.ts | 2 | ||||
| -rw-r--r-- | src/modules/person/index.ts | 112 | ||||
| -rw-r--r-- | src/modules/random/index.ts | 2 |
13 files changed, 191 insertions, 98 deletions
diff --git a/src/definitions/date.ts b/src/definitions/date.ts index 16cfb28a..2265a025 100644 --- a/src/definitions/date.ts +++ b/src/definitions/date.ts @@ -26,8 +26,9 @@ export interface DateEntryDefinition { /** * The short name/abbreviation of the entry. + * If null, the locale does not support a short name/abbreviation for the entry. */ - abbr: string[]; + abbr: string[] | null; /** * The wide name of the entry when used in context. If absent wide will be used instead. diff --git a/src/definitions/definitions.ts b/src/definitions/definitions.ts index ca495e34..c2a3b560 100644 --- a/src/definitions/definitions.ts +++ b/src/definitions/definitions.ts @@ -50,4 +50,4 @@ export type LocaleDefinition = { system?: SystemDefinition; vehicle?: VehicleDefinition; word?: WordDefinition; -} & Record<string, Record<string, unknown> | undefined>; +} & Record<string, Record<string, unknown>>; diff --git a/src/locale-proxy.ts b/src/locale-proxy.ts index 67b29d47..e99ba655 100644 --- a/src/locale-proxy.ts +++ b/src/locale-proxy.ts @@ -55,6 +55,30 @@ export function createLocaleProxy(locale: LocaleDefinition): LocaleProxy { } /** + * Checks that the value is not null or undefined and throws an error if it is. + * + * @param value The value to check. + * @param path The path to the locale data. + */ +export function assertLocaleData<T>( + value: T, + ...path: string[] +): asserts value is NonNullable<T> { + if (value === null) { + throw new FakerError( + `The locale data for '${path.join('.')}' aren't applicable to this locale. + If you think this is a bug, please report it at: https://github.com/faker-js/faker` + ); + } else if (value === undefined) { + throw new FakerError( + `The locale data for '${path.join('.')}' are missing in this locale. + Please contribute the missing data to the project or use a locale/Faker instance that has these data. + For more information see https://fakerjs.dev/guide/localization.html` + ); + } +} + +/** * Creates a proxy for a category that throws an error when accessing an undefined property. * * @param categoryName The name of the category. @@ -79,20 +103,10 @@ function createCategoryProxy< const value = target[entryName]; if (typeof entryName === 'symbol' || entryName === 'nodeType') { return value; - } else if (value === null) { - throw new FakerError( - `The locale data for '${categoryName}.${entryName.toString()}' aren't applicable to this locale. - If you think this is a bug, please report it at: https://github.com/faker-js/faker` - ); - } else if (value === undefined) { - throw new FakerError( - `The locale data for '${categoryName}.${entryName.toString()}' are missing in this locale. - Please contribute the missing data to the project or use a locale/Faker instance that has these data. - For more information see https://fakerjs.dev/guide/localization.html` - ); - } else { - return value; } + + assertLocaleData(value, categoryName, entryName.toString()); + return value; }, set: throwReadOnlyError, diff --git a/src/modules/airline/index.ts b/src/modules/airline/index.ts index 4c1ec318..e8ac47c5 100644 --- a/src/modules/airline/index.ts +++ b/src/modules/airline/index.ts @@ -155,7 +155,7 @@ export class AirlineModule extends ModuleBase { ): string { const { allowNumerics = false, allowVisuallySimilarCharacters = false } = options; - const excludedChars = []; + const excludedChars: string[] = []; if (!allowNumerics) { excludedChars.push(...numerics); } diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts index 5962ef71..57b906a3 100644 --- a/src/modules/color/index.ts +++ b/src/modules/color/index.ts @@ -47,17 +47,19 @@ export type Casing = 'lower' | 'upper' | 'mixed'; * * @param hexColor Hex color string to be formatted. * @param options Options object. - * @param options.prefix Prefix of the generated hex color. Defaults to `'0x'`. - * @param options.casing Letter type case of the generated hex color. Defaults to `'mixed'`. + * @param options.prefix Prefix of the generated hex color. + * @param options.casing Letter type case of the generated hex color. */ function formatHexColor( hexColor: string, - options?: { - prefix?: string; - casing?: Casing; + options: { + prefix: string; + casing: Casing; } ): string { - switch (options?.casing) { + const { prefix, casing } = options; + + switch (casing) { case 'upper': hexColor = hexColor.toUpperCase(); break; @@ -68,8 +70,8 @@ function formatHexColor( // Do nothing } - if (options?.prefix) { - hexColor = options.prefix + hexColor; + if (prefix) { + hexColor = prefix + hexColor; } return hexColor; @@ -360,19 +362,20 @@ export class ColorModule extends ModuleBase { */ includeAlpha?: boolean; }): string | number[]; - rgb(options?: { - prefix?: string; - casing?: Casing; - format?: 'hex' | ColorFormat; - includeAlpha?: boolean; - }): string | number[] { + rgb( + options: { + prefix?: string; + casing?: Casing; + format?: 'hex' | ColorFormat; + includeAlpha?: boolean; + } = {} + ): string | number[] { const { format = 'hex', includeAlpha = false, prefix = '#', casing = 'lower', - } = options || {}; - options = { format, includeAlpha, prefix, casing }; + } = options; let color: string | number[]; let cssFunction: CssFunctionType = 'rgb'; if (format === 'hex') { @@ -380,7 +383,7 @@ export class ColorModule extends ModuleBase { length: includeAlpha ? 8 : 6, prefix: '', }); - color = formatHexColor(color, options); + color = formatHexColor(color, { prefix, casing }); return color; } diff --git a/src/modules/commerce/index.ts b/src/modules/commerce/index.ts index 1be3fcb2..425bc848 100644 --- a/src/modules/commerce/index.ts +++ b/src/modules/commerce/index.ts @@ -1,3 +1,4 @@ +import { FakerError } from '../../errors/faker-error'; import { deprecated } from '../../internal/deprecated'; import { ModuleBase } from '../../internal/module-base'; @@ -401,7 +402,14 @@ export class CommerceModule extends ModuleBase { const registrantLength = groupRules.find( ([rangeMaximum]) => elementValue <= rangeMaximum - )[1]; + )?.[1]; + + if (!registrantLength) { + // This can only happen if the ISBN_LENGTH_RULES are corrupted + throw new FakerError( + `Unable to find a registrant length for the group ${group}` + ); + } const registrant = element.slice(0, registrantLength); const publication = element.slice(registrantLength); diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index a40b4772..39c85735 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -3,6 +3,7 @@ import type { DateEntryDefinition } from '../../definitions'; import { FakerError } from '../../errors/faker-error'; import { deprecated } from '../../internal/deprecated'; import { SimpleModuleBase } from '../../internal/module-base'; +import { assertLocaleData } from '../../locale-proxy'; /** * Converts date passed as a string, number or Date to a Date object. @@ -15,6 +16,10 @@ function toDate( date: string | Date | number | undefined, fallback: () => Date ): Date { + if (date == null) { + return fallback(); + } + date = new Date(date); if (Number.isNaN(date.valueOf())) { date = fallback(); @@ -383,14 +388,15 @@ export class SimpleDateModule extends SimpleModuleBase { }, legacyTo?: string | Date | number ): Date { - if (typeof options !== 'object' || options instanceof Date) { + if (options instanceof Date || typeof options !== 'object') { deprecated({ deprecated: 'faker.date.between(from, to)', proposed: 'faker.date.between({ from, to })', since: '8.0', until: '9.0', }); - options = { from: options, to: legacyTo }; + // We use options as fallback for legacyTo avoid TS errors for unintended usage. + options = { from: options, to: legacyTo ?? options }; } const { from, to } = options; @@ -559,14 +565,15 @@ export class SimpleDateModule extends SimpleModuleBase { legacyTo?: string | Date | number, legacyCount: number = 3 ): Date[] { - if (typeof options !== 'object' || options instanceof Date) { + if (options instanceof Date || typeof options !== 'object') { deprecated({ deprecated: 'faker.date.betweens(from, to, count)', proposed: 'faker.date.betweens({ from, to, count })', since: '8.0', until: '9.0', }); - options = { from: options, to: legacyTo, count: legacyCount }; + // We use options as fallback for legacyTo avoid TS errors for unintended usage. + options = { from: options, to: legacyTo ?? options, count: legacyCount }; } const { from, to, count = 3 } = options; @@ -864,12 +871,6 @@ export class SimpleDateModule extends SimpleModuleBase { refDate?: string | Date | number; } = {} ): Date { - if (options.max < options.min) { - throw new FakerError( - `Max ${options.max} should be larger than or equal to min ${options.min}.` - ); - } - const mode = options.mode === 'age' ? 'age' : 'year'; const refDate = toDate(options.refDate, this.faker.defaultRefDate); const refYear = refDate.getUTCFullYear(); @@ -894,6 +895,12 @@ export class SimpleDateModule extends SimpleModuleBase { ); } + if (max < min) { + throw new FakerError( + `Max ${options.max} should be larger than or equal to min ${options.min}.` + ); + } + return new Date(this.faker.number.int({ min, max })); } } @@ -1074,12 +1081,8 @@ export class DateModule extends SimpleDateModule { context?: boolean; } = {} ): string { - const { - // eslint-disable-next-line deprecation/deprecation - abbr, - abbreviated = abbr ?? false, - context = false, - } = options; + // eslint-disable-next-line deprecation/deprecation + const { abbr, abbreviated = abbr ?? false, context = false } = options; if (abbr != null) { deprecated({ @@ -1100,7 +1103,9 @@ export class DateModule extends SimpleDateModule { type = useContext ? 'wide_context' : 'wide'; } - return this.faker.helpers.arrayElement(source[type]); + const values = source[type]; + assertLocaleData(values, 'date.month', type); + return this.faker.helpers.arrayElement(values); } /** @@ -1260,12 +1265,8 @@ export class DateModule extends SimpleDateModule { context?: boolean; } = {} ): string { - const { - // eslint-disable-next-line deprecation/deprecation - abbr, - abbreviated = abbr ?? false, - context = false, - } = options; + // eslint-disable-next-line deprecation/deprecation + const { abbr, abbreviated = abbr ?? false, context = false } = options; if (abbr != null) { deprecated({ @@ -1286,6 +1287,8 @@ export class DateModule extends SimpleDateModule { type = useContext ? 'wide_context' : 'wide'; } - return this.faker.helpers.arrayElement(source[type]); + const values = source[type]; + assertLocaleData(values, 'date.weekday', type); + return this.faker.helpers.arrayElement(values); } } diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts index c443b605..33db26f0 100644 --- a/src/modules/finance/index.ts +++ b/src/modules/finance/index.ts @@ -24,6 +24,22 @@ export interface Currency { } /** + * Puts a space after every 4 characters. + * + * @internal + * + * @param iban The iban to pretty print. + */ +export function prettyPrintIban(iban: string): string { + let pretty = ''; + for (let i = 0; i < iban.length; i += 4) { + pretty += `${iban.substring(i, i + 4)} `; + } + + return pretty.trimEnd(); +} + +/** * Module to generate finance and money related entries. * * ### Overview @@ -663,9 +679,9 @@ export class FinanceModule extends ModuleBase { */ currencySymbol(): string { let symbol: string; - while (!symbol) { + do { symbol = this.currency().symbol; - } + } while (symbol.length === 0); return symbol; } @@ -1147,7 +1163,7 @@ export class FinanceModule extends ModuleBase { const result = `${ibanFormat.country}${checksum}${s}`; - return formatted ? result.match(/.{1,4}/g).join(' ') : result; + return formatted ? prettyPrintIban(result) : result; } /** diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index 59eeadba..667f3a51 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -1120,7 +1120,7 @@ export class SimpleHelpersModule extends SimpleModuleBase { ) => RecordKey, >( method: TMethod, - args: Parameters<TMethod> = [] as Parameters<TMethod>, + args: Parameters<TMethod> = [] as unknown as Parameters<TMethod>, options: { /** * This parameter does nothing. diff --git a/src/modules/helpers/unique.ts b/src/modules/helpers/unique.ts index 44b3a71d..20805530 100644 --- a/src/modules/helpers/unique.ts +++ b/src/modules/helpers/unique.ts @@ -97,9 +97,9 @@ export function exec< maxRetries = 50, currentIterations = 0, compare = defaultCompare, - store, + store = {}, } = options; - let { exclude } = options; + let { exclude = [] } = options; options.currentIterations = currentIterations; // Support single exclude argument as string diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts index 5eb9b4bc..8cc651a3 100644 --- a/src/modules/internet/index.ts +++ b/src/modules/internet/index.ts @@ -620,6 +620,7 @@ export class InternetModule extends ModuleBase { firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName; break; case 2: + default: result = `${firstName}${this.faker.helpers.arrayElement([ '.', '_', @@ -804,6 +805,7 @@ export class InternetModule extends ModuleBase { firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName; break; case 2: + default: result = `${firstName}${this.faker.helpers.arrayElement([ '.', '_', diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts index e0f4b6b0..0c5f79c3 100644 --- a/src/modules/person/index.ts +++ b/src/modules/person/index.ts @@ -1,5 +1,7 @@ import type { Faker } from '../..'; +import { FakerError } from '../../errors/faker-error'; import { ModuleBase } from '../../internal/module-base'; +import { assertLocaleData } from '../../locale-proxy'; export enum Sex { Female = 'female', @@ -18,6 +20,7 @@ export type SexType = `${Sex}`; * @param param2.generic Non-sex definitions. * @param param2.female Female definitions. * @param param2.male Male definitions. + * @param type Type of the definition. * * @returns Definition based on given sex. */ @@ -25,10 +28,14 @@ function selectDefinition<T>( faker: Faker, elementSelectorFn: (values: T[]) => string, sex: SexType | undefined, - // TODO @Shinigami92 2022-03-21: Remove fallback empty object when `strict: true` - { generic, female, male }: { generic?: T[]; female?: T[]; male?: T[] } = {} + { + generic, + female, + male, + }: { generic?: T[] | null; female?: T[] | null; male?: T[] | null }, + type: string ): string { - let values: T[] | undefined; + let values: T[] | undefined | null; switch (sex) { case Sex.Female: @@ -50,6 +57,8 @@ function selectDefinition<T>( } else { values = generic; } + + assertLocaleData(values, `person.{${type}, female_${type}, male_${type}}`); } return elementSelectorFn(values); @@ -92,11 +101,17 @@ export class PersonModule extends ModuleBase { const { first_name, female_first_name, male_first_name } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: first_name, - female: female_first_name, - male: male_first_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: first_name, + female: female_first_name, + male: male_first_name, + }, + 'first_name' + ); } /** @@ -135,16 +150,23 @@ export class PersonModule extends ModuleBase { generic: last_name_pattern, female: female_last_name_pattern, male: male_last_name_pattern, - } + }, + 'last_name_pattern' ); return this.faker.helpers.fake(pattern); } - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: last_name, - female: female_last_name, - male: male_last_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: last_name, + female: female_last_name, + male: male_last_name, + }, + 'last_name' + ); } /** @@ -164,11 +186,17 @@ export class PersonModule extends ModuleBase { const { middle_name, female_middle_name, male_middle_name } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: middle_name, - female: female_middle_name, - male: male_middle_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: middle_name, + female: female_middle_name, + male: male_middle_name, + }, + 'middle_name' + ); } /** @@ -305,11 +333,17 @@ export class PersonModule extends ModuleBase { const { prefix, female_prefix, male_prefix } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: prefix, - female: female_prefix, - male: male_prefix, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: prefix, + female: female_prefix, + male: male_prefix, + }, + 'prefix' + ); } /** @@ -350,9 +384,13 @@ export class PersonModule extends ModuleBase { * @since 8.0.0 */ jobDescriptor(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.descriptor - ); + const values = this.faker.definitions.person.title.descriptor; + + if (values == null) { + throw new FakerError('No person.title.descriptor definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** @@ -364,9 +402,13 @@ export class PersonModule extends ModuleBase { * @since 8.0.0 */ jobArea(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.level - ); + const values = this.faker.definitions.person.title.level; + + if (values == null) { + throw new FakerError('No person.title.area definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** @@ -378,9 +420,13 @@ export class PersonModule extends ModuleBase { * @since 8.0.0 */ jobType(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.job - ); + const values = this.faker.definitions.person.title.job; + + if (values == null) { + throw new FakerError('No person.title.job definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** diff --git a/src/modules/random/index.ts b/src/modules/random/index.ts index 997583c1..474e8ca6 100644 --- a/src/modules/random/index.ts +++ b/src/modules/random/index.ts @@ -123,7 +123,7 @@ export class RandomModule extends ModuleBase { '_', '-', ]; - let result: string; + let result = ''; let iteration = 0; |
