feat: add stylisticTypeChecked preset with targeted overrides

Added @typescript-eslint/stylistic-type-checked preset with selective overrides for our deliberate choices:

Preset Benefits:
- 30+ battle-tested stylistic rules from the TypeScript ESLint team
- Automatic maintenance and updates
- Comprehensive coverage of TypeScript-specific patterns

Targeted Overrides:
- array-type: "array-simple" for better readability on complex types
- consistent-generic-constructors: "type-annotation" to keep generics on left side
- no-inferrable-types: "off" to avoid conflicts with typedef strictness
- non-nullable-type-assertion-style: "off" to avoid conflicts with strict rules

Manual Fixes Applied:
- prefer-nullish-coalescing: library.ts, users.ts, users.spec.ts
- prefer-optional-chain: users.ts
- no-empty-function: logger.spec.ts, library.spec.ts
- array-type: auto-fixed across multiple test files

Zero ESLint violations remaining
This commit is contained in:
Venkatesan Ravi
2025-11-22 14:21:20 -08:00
parent 1eb2e343b9
commit 5d55e409ef
8 changed files with 39 additions and 13 deletions

View File

@@ -5,6 +5,7 @@ import tseslint from "typescript-eslint";
export default defineConfig(
eslint.configs.recommended,
tseslint.configs.strictTypeChecked,
tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
@@ -76,6 +77,25 @@ export default defineConfig(
format: ["camelCase", "PascalCase", "UPPER_CASE"],
},
],
// conflicts with typedef strictness
"@typescript-eslint/no-inferrable-types": "off",
// conflicts with strict rules
"@typescript-eslint/non-nullable-type-assertion-style": "off",
// enforce array-simple for better readability on complex types
"@typescript-eslint/array-type": [
"error",
{
default: "array-simple",
readonly: "array-simple",
},
],
// keep generics on left side for consistency
"@typescript-eslint/consistent-generic-constructors": [
"error",
"type-annotation",
],
},
},
[

View File

@@ -34,7 +34,7 @@ export function calculateLibraryDiff(
virtualFoldersToCreate.push(desiredVF);
} else {
// Check if locations differ
const currentLocations: string[] = existingVF.Locations || [];
const currentLocations: string[] = existingVF.Locations ?? [];
const desiredLocations: string[] = desiredVF.libraryOptions.pathInfos.map(
(p: { path: string }) => p.path,
);

View File

@@ -60,12 +60,12 @@ export function calculateUserPoliciesDiff(
(user: UserDtoSchema) => user.Name === desiredUser.name,
);
if (existingUser && existingUser.Id && desiredUser.policy) {
if (existingUser?.Id && desiredUser.policy) {
const updatedPolicy: Partial<UserPolicySchema> =
mapUserPolicyConfigToSchema(desiredUser.policy);
const currentPolicy: Partial<UserPolicySchema> =
existingUser.Policy || {};
existingUser.Policy ?? {};
const newPolicy: UserPolicySchema = {
...currentPolicy,
...updatedPolicy,

View File

@@ -306,7 +306,7 @@ describe("apply/encoding", () => {
it("should not modify HardwareAccelerationType when value is the same", () => {
// Arrange
const testCases: Array<string> = [
const testCases: string[] = [
"none",
"amf",
"qsv",

View File

@@ -14,8 +14,8 @@ describe("apply/library", () => {
vi.clearAllMocks();
addVirtualFolderSpy = vi.fn();
loggerSpy = vi.spyOn(logger, "info").mockImplementation(() => {});
vi.spyOn(logger, "warn").mockImplementation(() => {});
loggerSpy = vi.spyOn(logger, "info").mockImplementation(() => undefined);
vi.spyOn(logger, "warn").mockImplementation(() => undefined);
mockClient = {
addVirtualFolder: addVirtualFolderSpy,
@@ -158,7 +158,7 @@ describe("apply/library", () => {
// Arrange
const warnSpy: Mock = vi
.spyOn(logger, "warn")
.mockImplementation(() => {});
.mockImplementation(() => undefined);
const currentVirtualFolders: VirtualFolderInfoSchema[] = [
{
Name: "Movies",

View File

@@ -24,7 +24,7 @@ vi.mock("../../src/lib/logger", () => ({
vi.mock("../../src/mappers/users", () => ({
mapUserConfigToCreateSchema: vi.fn((config: UserConfig) => ({
Name: config.name,
Password: config.password || "mocked-password-from-file",
Password: config.password ?? "mocked-password-from-file",
})),
mapUserPolicyConfigToSchema: vi.fn(
(policy: {

View File

@@ -4,7 +4,9 @@ import { logger } from "../../src/lib/logger";
describe("lib/logger", () => {
it("whenInfoCalled_thenWritesToConsoleLog()", () => {
// Arrange
const spy: Mock = vi.spyOn(console, "log").mockImplementation(() => {});
const spy: Mock = vi
.spyOn(console, "log")
.mockImplementation(() => undefined);
// Act
logger.info("hello");
@@ -17,7 +19,9 @@ describe("lib/logger", () => {
it("whenWarnCalled_thenWritesToConsoleWarn()", () => {
// Arrange
const spy: Mock = vi.spyOn(console, "warn").mockImplementation(() => {});
const spy: Mock = vi
.spyOn(console, "warn")
.mockImplementation(() => undefined);
// Act
logger.warn("w");
@@ -30,7 +34,9 @@ describe("lib/logger", () => {
it("whenErrorCalled_thenWritesToConsoleError()", () => {
// Arrange
const spy: Mock = vi.spyOn(console, "error").mockImplementation(() => {});
const spy: Mock = vi
.spyOn(console, "error")
.mockImplementation(() => undefined);
// Act
logger.error("e");

View File

@@ -395,7 +395,7 @@ describe("UserPolicyConfig", () => {
it("should validate policy with individual fields", () => {
// Arrange
const validConfigs: z.input<typeof UserPolicyConfigType>[] = [
const validConfigs: Array<z.input<typeof UserPolicyConfigType>> = [
{ isAdministrator: true },
{ isAdministrator: false },
{ loginAttemptsBeforeLockout: 10 },
@@ -487,7 +487,7 @@ describe("UserPolicyConfig", () => {
it("should reject non-boolean policy fields", () => {
// Arrange
const invalidConfigs: z.input<typeof UserPolicyConfigType>[] = [
const invalidConfigs: Array<z.input<typeof UserPolicyConfigType>> = [
// @ts-expect-error intentional bad types for test
{ isAdministrator: "true" },
];