Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

infra(tsconfig): noImplicitAny #2562

Merged
merged 5 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .prettierrc.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { Options } from 'prettier';

declare const options: Options;
export = options;
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion scripts/apidoc/typedoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export function selectApiModules(
.getChildrenByKind(ReflectionKind.Class)
.filter(
(module) =>
faker[extractModuleFieldName(module)] != null || includeTestModules
faker[extractModuleFieldName(module) as keyof typeof faker] != null ||
includeTestModules
);
}

Expand Down
21 changes: 8 additions & 13 deletions scripts/generate-locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ import {
} from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Options } from 'prettier';
import { format } from 'prettier';
import options from '../.prettierrc.js';
import type { LocaleDefinition, MetadataDefinition } from '../src/definitions';
import { formatMarkdown, formatTypescript } from './apidoc/format';

// Constants

Expand Down Expand Up @@ -78,9 +76,6 @@ const definitionsTypes: DefinitionType = {
word: 'WordDefinition',
};

const prettierTsOptions: Options = { ...options, parser: 'typescript' };
const prettierMdOptions: Options = { ...options, parser: 'markdown' };

const scriptCommand = 'pnpm run generate:locales';

const autoGeneratedCommentHeader = `/*
Expand Down Expand Up @@ -154,7 +149,7 @@ async function generateLocaleFile(locale: string): Promise<void> {
});
`;

content = await format(content, prettierTsOptions);
content = await formatTypescript(content);
writeFileSync(resolve(pathLocale, `${locale}.ts`), content);
}

Expand Down Expand Up @@ -195,7 +190,7 @@ async function generateLocalesIndexFile(

writeFileSync(
resolve(path, 'index.ts'),
await format(content.join('\n'), prettierTsOptions)
await formatTypescript(content.join('\n'))
);
}

Expand Down Expand Up @@ -301,7 +296,7 @@ async function normalizeLocaleFile(filePath: string, definitionKey: string) {
}

const result = {} as T;
for (const key of Object.keys(localeData)) {
for (const key of Object.keys(localeData) as Array<keyof T>) {
result[key] = normalizeDataRecursive(localeData[key]);
}

Expand Down Expand Up @@ -367,7 +362,7 @@ async function normalizeLocaleFile(filePath: string, definitionKey: string) {
// In the long term we should probably define a whether we want those in the files at all.
const newContent = fileContentPreData + JSON.stringify(localeData);

writeFileSync(filePath, await format(newContent, prettierTsOptions));
writeFileSync(filePath, await formatTypescript(newContent));
}

// Start of actual logic
Expand Down Expand Up @@ -444,7 +439,7 @@ async function main(): Promise<void> {
} as const;
`;

localeIndexContent = await format(localeIndexContent, prettierTsOptions);
localeIndexContent = await formatTypescript(localeIndexContent);
writeFileSync(pathLocaleIndex, localeIndexContent);

// src/locales/index.ts
Expand All @@ -455,12 +450,12 @@ async function main(): Promise<void> {
${localesIndexExports}
`;

localesIndexContent = await format(localesIndexContent, prettierTsOptions);
localesIndexContent = await formatTypescript(localesIndexContent);
writeFileSync(pathLocalesIndex, localesIndexContent);

// docs/guide/localization.md

localizationLocales = await format(localizationLocales, prettierMdOptions);
localizationLocales = await formatMarkdown(localizationLocales);

let localizationContent = readFileSync(pathDocsGuideLocalization, 'utf8');
localizationContent = localizationContent.replace(
Expand Down
11 changes: 6 additions & 5 deletions test/all-functional.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ function isTestableModule(moduleName: string): moduleName is keyof Faker {
}

function getMethodNamesOf(module: object): string[] {
return Object.keys(module).filter(isMethodOf(module));
}

function isMethodOf(module: object): (method: string) => boolean {
return (method: string) => typeof module[method] === 'function';
return (Object.keys(module) as Array<keyof typeof module>).filter(
(method) => typeof module[method] === 'function'
);
}

type SkipConfig<TModule> = Partial<
Expand Down Expand Up @@ -81,6 +79,7 @@ function isWorkingLocaleForMethod(
method: string,
locale: string
): boolean {
// @ts-expect-error: We don't have types for the dynamic access
const broken = BROKEN_LOCALE_METHODS[module]?.[method] ?? [];
return broken !== '*' && !broken.includes(locale);
}
Expand All @@ -104,6 +103,7 @@ describe('BROKEN_LOCALE_METHODS test', () => {
it('should not contain obsolete configuration (methods)', () => {
const existingMethods = modules[module];
const configuredMethods = Object.keys(
// @ts-expect-error: We don't have types for the dynamic access
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
BROKEN_LOCALE_METHODS[module] ?? {}
);
Expand All @@ -129,6 +129,7 @@ describe('functional tests', () => {
const testAssertion = () => {
// TODO @ST-DDT 2022-03-28: Use random seed once there are no more failures
faker.seed(1);
// @ts-expect-error: We don't have types for the dynamic access
const result = faker[module][meth]();

if (meth === 'boolean') {
Expand Down
4 changes: 3 additions & 1 deletion test/faker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ describe('faker', () => {
});

it('should not log anything on startup', () => {
const spies: SpyInstance[] = Object.keys(console)
const spies: SpyInstance[] = (
Object.keys(console) as Array<keyof typeof console>
)
.filter((key) => typeof console[key] === 'function')
.map((methodName) =>
vi.spyOn(console, methodName as keyof typeof console)
Expand Down
115 changes: 59 additions & 56 deletions test/locale-imports.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,67 @@ import { describe, expect, it } from 'vitest';
import type { Faker } from '../src';
import { allLocales } from '../src';

describe.each(Object.keys(allLocales))('locale imports', (locale) => {
it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module
const { faker } = require(`../dist/cjs/locale/${locale}`) as {
faker: Faker;
};
describe.each(Object.keys(allLocales) as Array<keyof typeof allLocales>)(
'locale imports',
(locale) => {
it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module
const { faker } = require(`../dist/cjs/locale/${locale}`) as {
faker: Faker;
};

expect(faker).toBeDefined();
expect(faker.string.alpha()).toBeTypeOf('string');
expect(faker.definitions.metadata.title).toBe(
allLocales[locale].metadata.title
);
});
expect(faker).toBeDefined();
expect(faker.string.alpha()).toBeTypeOf('string');
expect(faker.definitions.metadata.title).toBe(
allLocales[locale].metadata?.title
);
});

it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => {
const { faker } = (await import(`../dist/esm/locale/${locale}`)) as {
faker: Faker;
};
it(`should be possible to directly import('@faker-js/faker/locale/${locale}')`, async () => {
const { faker } = (await import(`../dist/esm/locale/${locale}`)) as {
faker: Faker;
};

expect(faker).toBeDefined();
expect(faker.string.alpha()).toBeTypeOf('string');
expect(faker.definitions.metadata.title).toBe(
allLocales[locale].metadata.title
);
});
expect(faker).toBeDefined();
expect(faker.string.alpha()).toBeTypeOf('string');
expect(faker.definitions.metadata.title).toBe(
allLocales[locale].metadata?.title
);
});

it('should have complete metadata values', () => {
const metadata = allLocales[locale].metadata;
expect(metadata.title).toBeTypeOf('string');
expect(metadata.code).toBeTypeOf('string');
expect(metadata.code).toEqual(locale);
if (locale !== 'base') {
expect(metadata.language).toBeTypeOf('string');
expect(metadata.language).toMatch(/^[a-z]{2}$/);
expect(metadata.script).toBeTypeOf('string');
expect([
'Arab',
'Armn',
'Cyrl',
'Deva',
'Geor',
'Grek',
'Hans',
'Hant',
'Hebr',
'Jpan',
'Kore',
'Latn',
'Thaa',
'Thai',
]).toContain(metadata.script);
expect(metadata.endonym).toBeTypeOf('string');
expect(metadata.dir).toBeTypeOf('string');
expect(['ltr', 'rtl']).toContain(metadata.dir);
if (metadata.country) {
expect(metadata.country).toBeTypeOf('string');
expect(metadata.country).toMatch(/^[A-Z]{2}$/);
it('should have complete metadata values', () => {
const metadata = allLocales[locale].metadata ?? {};
expect(metadata.title).toBeTypeOf('string');
expect(metadata.code).toBeTypeOf('string');
expect(metadata.code).toEqual(locale);
if (locale !== 'base') {
expect(metadata.language).toBeTypeOf('string');
expect(metadata.language).toMatch(/^[a-z]{2}$/);
expect(metadata.script).toBeTypeOf('string');
expect([
'Arab',
'Armn',
'Cyrl',
'Deva',
'Geor',
'Grek',
'Hans',
'Hant',
'Hebr',
'Jpan',
'Kore',
'Latn',
'Thaa',
'Thai',
]).toContain(metadata.script);
expect(metadata.endonym).toBeTypeOf('string');
expect(metadata.dir).toBeTypeOf('string');
expect(['ltr', 'rtl']).toContain(metadata.dir);
if (metadata.country) {
expect(metadata.country).toBeTypeOf('string');
expect(metadata.country).toMatch(/^[A-Z]{2}$/);
}
}
}
});
});
});
}
);
8 changes: 5 additions & 3 deletions test/modules/helpers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest';
import { faker, FakerError } from '../../src';
import { luhnCheck } from '../../src/modules/helpers/luhn-check';
import type { RecordKey } from '../../src/modules/helpers/unique';
import { seededTests } from '../support/seeded-runs';
import { times } from './../support/times';
import './../vitest-extensions';
Expand Down Expand Up @@ -1295,8 +1296,9 @@ Try adjusting maxTime or maxRetries parameters for faker.helpers.unique().`)
const maxTime = 49;
const maxRetries = 49;
const currentIterations = 0;
const exclude = [];
const compare = (obj, key) => (obj[key] === undefined ? -1 : 0);
const exclude: string[] = [];
const compare = (obj: Record<RecordKey, RecordKey>, key: RecordKey) =>
obj[key] === undefined ? -1 : 0;

const options = {
startTime,
Expand All @@ -1318,7 +1320,7 @@ Try adjusting maxTime or maxRetries parameters for faker.helpers.unique().`)
});

it('should be possible to pass a user-specific store', () => {
const store = {};
const store: Record<string, string> = {};

const method = () => 'with conflict: 0';

Expand Down
2 changes: 1 addition & 1 deletion test/modules/image.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ describe('image', () => {
'objects',
'people',
'technology',
];
] satisfies Array<keyof typeof faker.image.unsplash>;

describe.each(categories)(`%s()`, (category) => {
it(`should return a random ${category} image url`, () => {
Expand Down
8 changes: 4 additions & 4 deletions test/simple-faker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { SimpleFaker, simpleFaker } from '../src';

describe('simpleFaker', () => {
it('should not log anything on startup', () => {
const spies: SpyInstance[] = Object.keys(console)
const spies: SpyInstance[] = (
Object.keys(console) as Array<keyof typeof console>
)
.filter((key) => typeof console[key] === 'function')
.map((methodName) =>
vi.spyOn(console, methodName as keyof typeof console)
);
.map((methodName) => vi.spyOn(console, methodName));

// eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module -- Using import() requires types being build but the CI / TS-Check runs without them.
require('..').simpleFaker;
Expand Down
1 change: 0 additions & 1 deletion tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"outDir": "dist/types",

// This negates what is set in the extended tsconfig.json
"noImplicitAny": true,
"skipLibCheck": false,
"allowSyntheticDefaultImports": false,
"resolveJsonModule": false
Expand Down
3 changes: 0 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
"declaration": true,
"stripInternal": true,

// We need to disable these for now, and need to tackle them in another PR
"noImplicitAny": false,

// These are configs specifically for !build and have to be reverted in the tsconfig.build.json
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
Expand Down