Skip to content

Commit

Permalink
fix: writing TypeScript config file
Browse files Browse the repository at this point in the history
  • Loading branch information
rubiesonthesky committed Jan 7, 2025
1 parent 881cd89 commit d05243b
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { describe, expect, it } from "vitest";

import { InitializationImprovement } from "./improvements.js";
import { generateMultiTypeScriptConfig } from "./writeMultiTypeScriptConfig.js";

describe("writeMultiTypeScriptConfig", () => {
it("creates multi TypeScript config", () => {
const config = generateMultiTypeScriptConfig({
fileName: "typestat.json",
improvements: new Set([
InitializationImprovement.MissingProperties,
InitializationImprovement.NoImplicitAny,
InitializationImprovement.NoImplicitThis,
InitializationImprovement.NoInferableTypes,
InitializationImprovement.StrictNullChecks,
]),
project: { filePath: "./tsconfig.json" },
testFiles: "test/**/*.{ts,tsx}",
});

expect(config).toStrictEqual([
{
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
strictNonNullAssertions: true,
},
include: ["test/**/*.{ts,tsx}"],
projectPath: "./tsconfig.json",
types: {
strictNullChecks: true,
},
},
{
exclude: ["test/**/*.{ts,tsx}"],
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
},
projectPath: "./tsconfig.json",
},
{
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
},
include: ["test/**/*.{ts,tsx}"],
projectPath: "./tsconfig.json",
},
]);
});
});
110 changes: 62 additions & 48 deletions src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from "node:fs/promises";

import { Fixes, RawTypeStatOptions } from "../../options/types.js";
import { ProjectDescription } from "../initializeProject/shared.js";
import { InitializationImprovement } from "./improvements.js";

Expand All @@ -11,61 +12,74 @@ export interface MultiTypeScriptConfigSettings {
testFiles?: string;
}

export const writeMultiTypeScriptConfig = async ({
fileName,
export const writeMultiTypeScriptConfig = async (
settings: MultiTypeScriptConfigSettings,
) => {
const config = generateMultiTypeScriptConfig(settings);
await fs.writeFile(settings.fileName, JSON.stringify(config, undefined, 4));
};

Check warning on line 20 in src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts#L16-L20

Added lines #L16 - L20 were not covered by tests

export const generateMultiTypeScriptConfig = ({
improvements,
project,
sourceFiles,
testFiles,
}: MultiTypeScriptConfigSettings) => {
await fs.writeFile(
fileName,
JSON.stringify(
[
{
fixes: {
...printImprovements(improvements),
strictNonNullAssertions: true,
},
...(testFiles && { include: [testFiles] }),
projectPath: project.filePath,
types: {
strictNullChecks: true,
},
},
{
...(testFiles && { exclude: [testFiles] }),
fixes: printImprovements(improvements),
...(sourceFiles && { include: [sourceFiles] }),
projectPath: project.filePath,
},
{
fixes: printImprovements(improvements),
...(testFiles
? { include: [testFiles, sourceFiles] }
: { include: [sourceFiles] }),
projectPath: project.filePath,
},
],
undefined,
4,
),
);
const fixes = printImprovements(improvements);

const stage1: Partial<RawTypeStatOptions> = {
fixes: {
...fixes,
strictNonNullAssertions: true,
},
projectPath: project.filePath,
types: {
strictNullChecks: true,
},
};

const stage2: Partial<RawTypeStatOptions> = {
fixes,
projectPath: project.filePath,
};

const stage3: Partial<RawTypeStatOptions> = {
fixes,
projectPath: project.filePath,
};

if (testFiles) {
// @ts-expect-error Cannot assign to 'include' because it is a read-only property.
stage1.include = [testFiles];
// @ts-expect-error Property 'exclude' does not exist on type 'Partial<PendingTypeStatOptions>'.
stage2.exclude = [testFiles];
// @ts-expect-error Cannot assign to 'include' because it is a read-only property.
stage3.include = [testFiles, sourceFiles].filter(Boolean);
} else {
// @ts-expect-error Cannot assign to 'include' because it is a read-only property.
stage3.include = [sourceFiles].filter(Boolean);
}

Check warning on line 61 in src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts#L60-L61

Added lines #L60 - L61 were not covered by tests

if (sourceFiles) {
// @ts-expect-error Cannot assign to 'include' because it is a read-only property.
stage2.include = [sourceFiles];
}

Check warning on line 66 in src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeMultiTypeScriptConfig.ts#L65-L66

Added lines #L65 - L66 were not covered by tests

return [stage1, stage2, stage3];
};

const printImprovements = (
improvements: ReadonlySet<InitializationImprovement>,
) => {
return {
incompleteTypes: true,
...(improvements.has(InitializationImprovement.NoImplicitAny) && {
noImplicitAny: true,
}),
...(improvements.has(InitializationImprovement.NoInferableTypes) && {
inferableTypes: true,
}),
...(improvements.has(InitializationImprovement.NoImplicitThis) && {
noImplicitThis: true,
}),
};
): Partial<Fixes> => {
const fixes: Partial<Fixes> = { incompleteTypes: true };
if (improvements.has(InitializationImprovement.NoImplicitAny)) {
fixes.noImplicitAny = true;
}
if (improvements.has(InitializationImprovement.NoInferableTypes)) {
fixes.noInferableTypes = true;
}
if (improvements.has(InitializationImprovement.NoImplicitThis)) {
fixes.noImplicitThis = true;
}
return fixes;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { describe, expect, it } from "vitest";

import { InitializationImprovement } from "./improvements.js";
import { generateSingleTypeScriptConfig } from "./writeSingleTypeScriptConfig.js";

describe("writeMultiTypeScriptConfig", () => {
it("creates multi TypeScript config", () => {
const config = generateSingleTypeScriptConfig({
fileName: "typestat.json",
improvements: new Set([InitializationImprovement.NoImplicitAny]),
project: { filePath: "./tsconfig.json" },
});

expect(config).toStrictEqual({
fixes: {
incompleteTypes: true,
noImplicitAny: true,
},
projectPath: "./tsconfig.json",
});
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from "node:fs/promises";

import { Fixes, RawTypeStatOptions } from "../../options/types.js";
import { ProjectDescription } from "../initializeProject/shared.js";
import { InitializationImprovement } from "./improvements.js";

Expand All @@ -10,36 +11,39 @@ export interface SingleTypeScriptConfigSettings {
sourceFiles?: string;
}

export const writeSingleTypeScriptConfig = async ({
fileName,
export const writeSingleTypeScriptConfig = async (
settings: SingleTypeScriptConfigSettings,
) => {
const config = generateSingleTypeScriptConfig(settings);
await fs.writeFile(settings.fileName, JSON.stringify(config, undefined, 4));
};

Check warning on line 19 in src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts#L15-L19

Added lines #L15 - L19 were not covered by tests

export const generateSingleTypeScriptConfig = ({
improvements,
project,
sourceFiles,
}: SingleTypeScriptConfigSettings) => {
await fs.writeFile(
fileName,
JSON.stringify(
{
fixes: printImprovements(improvements),
...(sourceFiles && { include: [sourceFiles] }),
projectPath: project.filePath,
},
undefined,
4,
),
);
const config: Partial<RawTypeStatOptions> = {
fixes: printImprovements(improvements),
projectPath: project.filePath,
};

if (sourceFiles) {
// @ts-expect-error Cannot assign to 'include' because it is a read-only property.
config.include = [sourceFiles];
}

Check warning on line 34 in src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts#L33-L34

Added lines #L33 - L34 were not covered by tests
return config;
};

const printImprovements = (
improvements: ReadonlySet<InitializationImprovement>,
) => {
return {
incompleteTypes: true,
...(improvements.has(InitializationImprovement.NoImplicitAny) && {
noImplicitAny: true,
}),
...(improvements.has(InitializationImprovement.NoImplicitThis) && {
noImplicitThis: true,
}),
};
): Partial<Fixes> => {
const fixes: Partial<Fixes> = { incompleteTypes: true };
if (improvements.has(InitializationImprovement.NoImplicitAny)) {
fixes.noImplicitAny = true;
}
if (improvements.has(InitializationImprovement.NoImplicitThis)) {
fixes.noImplicitThis = true;
}

Check warning on line 47 in src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts

View check run for this annotation

Codecov / codecov/patch

src/initialization/initializeTypeScript/writeSingleTypeScriptConfig.ts#L46-L47

Added lines #L46 - L47 were not covered by tests
return fixes;
};

0 comments on commit d05243b

Please sign in to comment.