Skip to content

Commit 290d60c

Browse files
heiskrCopilot
andauthored
Replace explicit any types with proper TypeScript types (#59127)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 5de57dd commit 290d60c

File tree

14 files changed

+85
-40
lines changed

14 files changed

+85
-40
lines changed

src/content-linter/lib/linting-rules/rai-reusable-usage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { RuleParams, RuleErrorCallback, Rule } from '../../types'
1010
interface Frontmatter {
1111
type?: string
1212
// Allow any additional frontmatter properties since we only care about 'type'
13-
[key: string]: any
13+
[key: string]: unknown
1414
}
1515

1616
interface LiquidToken {

src/content-render/scripts/cta-builder.ts

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ interface CTAParams {
1818
ref_style?: string
1919
}
2020

21+
const CTA_PARAM_KEYS: (keyof CTAParams)[] = ['ref_product', 'ref_plan', 'ref_type', 'ref_style']
22+
23+
interface CTASchemaProperty {
24+
type: string
25+
name: string
26+
description: string
27+
enum: string[]
28+
}
29+
30+
type CTASchemaProperties = {
31+
[K in keyof CTAParams]-?: CTASchemaProperty
32+
}
33+
2134
// Conversion mappings from old CTA format to new schema
2235
const ctaToTypeMapping: Record<string, string> = {
2336
'GHEC trial': 'trial',
@@ -153,27 +166,40 @@ function extractCTAParams(url: string): CTAParams {
153166
const urlObj = new URL(url)
154167
const ctaParams: CTAParams = {}
155168
for (const [key, value] of urlObj.searchParams.entries()) {
156-
if (key.startsWith('ref_')) {
157-
;(ctaParams as any)[key] = value
169+
if (key.startsWith('ref_') && CTA_PARAM_KEYS.includes(key as keyof CTAParams)) {
170+
ctaParams[key as keyof CTAParams] = value
158171
}
159172
}
160173
return ctaParams
161174
}
162175

176+
interface AjvErrorParams {
177+
missingProperty?: string
178+
allowedValues?: string[]
179+
additionalProperty?: string
180+
}
181+
182+
interface AjvError {
183+
keyword: string
184+
instancePath: string
185+
message?: string
186+
params: AjvErrorParams
187+
}
188+
163189
// Process AJV validation errors into readable messages
164-
function formatValidationErrors(ctaParams: CTAParams, errors: any[]): string[] {
190+
function formatValidationErrors(ctaParams: CTAParams, errors: AjvError[]): string[] {
165191
const errorMessages: string[] = []
166192
for (const error of errors) {
167193
let message = ''
168194
if (error.keyword === 'required') {
169-
message = `Missing required parameter: ${(error.params as any)?.missingProperty}`
195+
message = `Missing required parameter: ${error.params.missingProperty}`
170196
} else if (error.keyword === 'enum') {
171197
const paramName = error.instancePath.substring(1)
172198
const invalidValue = ctaParams[paramName as keyof CTAParams]
173-
const allowedValues = (error.params as any)?.allowedValues || []
199+
const allowedValues = error.params.allowedValues || []
174200
message = `Invalid value for ${paramName}: "${invalidValue}". Valid values are: ${allowedValues.join(', ')}`
175201
} else if (error.keyword === 'additionalProperties') {
176-
message = `Unexpected parameter: ${(error.params as any)?.additionalProperty}`
202+
message = `Unexpected parameter: ${error.params.additionalProperty}`
177203
} else {
178204
message = `Validation error: ${error.message}`
179205
}
@@ -191,7 +217,7 @@ function validateCTAParams(params: CTAParams): { isValid: boolean; errors: strin
191217
return { isValid: true, errors: [] }
192218
}
193219

194-
const errors = formatValidationErrors(params, ajvErrors)
220+
const errors = formatValidationErrors(params, ajvErrors as unknown as AjvError[])
195221
return {
196222
isValid: false,
197223
errors,
@@ -382,12 +408,14 @@ async function interactiveBuilder(): Promise<void> {
382408

383409
// Required parameters
384410
console.log(chalk.white(`\nRequired parameters:`))
411+
const schemaProps = ctaSchema.properties as CTASchemaProperties
385412

386413
for (const requiredParam of ctaSchema.required) {
387-
;(params as any)[requiredParam] = await selectFromOptions(
414+
const paramKey = requiredParam as keyof CTAParams
415+
params[paramKey] = await selectFromOptions(
388416
requiredParam,
389-
(ctaSchema.properties as any)[requiredParam].description,
390-
(ctaSchema.properties as any)[requiredParam].enum,
417+
schemaProps[paramKey].description,
418+
schemaProps[paramKey].enum,
391419
prompt,
392420
)
393421
}
@@ -399,15 +427,16 @@ async function interactiveBuilder(): Promise<void> {
399427
const optionalProperties = allProperties.filter((prop) => !ctaSchema.required.includes(prop))
400428

401429
for (const optionalParam of optionalProperties) {
430+
const paramKey = optionalParam as keyof CTAParams
402431
const includeParam = await confirmChoice(
403-
`Include ${(ctaSchema.properties as any)[optionalParam].name.toLowerCase()}?`,
432+
`Include ${schemaProps[paramKey].name.toLowerCase()}?`,
404433
prompt,
405434
)
406435
if (includeParam) {
407-
;(params as any)[optionalParam] = await selectFromOptions(
436+
params[paramKey] = await selectFromOptions(
408437
optionalParam,
409-
(ctaSchema.properties as any)[optionalParam].description,
410-
(ctaSchema.properties as any)[optionalParam].enum,
438+
schemaProps[paramKey].description,
439+
schemaProps[paramKey].enum,
411440
prompt,
412441
)
413442
}

src/content-render/tests/liquid-helpers.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
33
import { liquid } from '@/content-render/index'
44
import languages from '@/languages/lib/languages-server'
55
import { DataDirectory } from '@/tests/helpers/data-directory'
6+
import type { Context } from '@/types'
67

78
describe('liquid helper tags', () => {
89
vi.setConfig({ testTimeout: 60 * 1000 })
910

10-
// Using 'any' type as context is a test fixture with dynamic properties set in beforeAll
11-
const context: any = {}
12-
// Using 'any' type as DataDirectory is from data-directory.ts which lacks type definitions
13-
let dd: any
11+
const context: Partial<Context> = {}
12+
let dd: DataDirectory
1413
const enDirBefore = languages.en.dir
1514

1615
beforeAll(() => {

src/content-render/tests/liquid-tags.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ describe('liquid-tags script integration tests', () => {
3131
stdio: 'pipe',
3232
timeout: 30000,
3333
})
34-
} catch (error: any) {
35-
output = error.stdout + error.stderr
36-
exitCode = error.status || 1
34+
} catch (error: unknown) {
35+
const execError = error as { stdout?: string; stderr?: string; status?: number }
36+
output = (execError.stdout || '') + (execError.stderr || '')
37+
exitCode = execError.status || 1
3738
}
3839

3940
return { output, exitCode }

src/events/components/is-headless.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare global {
44
interface Window {
5-
GHDOCSPLAYWRIGHT: any
5+
GHDOCSPLAYWRIGHT: boolean | number
66
}
77
}
88

src/frame/middleware/context/product-examples.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function getProductExampleData(
1616
try {
1717
return getDataByLanguage(`product-examples.${product}.${key}`, language)
1818
} catch (error) {
19-
if (error instanceof Error && (error as any).code === 'ENOENT') return
19+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return
2020
throw error
2121
}
2222
}

src/frame/tests/find-page.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { describe, expect, test, vi } from 'vitest'
55

66
import Page from '@/frame/lib/page'
77
import findPage from '@/frame/lib/find-page'
8+
import type { Page as PageType } from '@/types'
89

910
const __dirname = path.dirname(fileURLToPath(import.meta.url))
1011

@@ -31,7 +32,7 @@ describe('find page', () => {
3132

3233
const redirectedPage = findPage(
3334
redirectToFind,
34-
pageMap as any, // Using any due to type conflicts between different Page type definitions
35+
pageMap as unknown as Record<string, PageType>,
3536
page.buildRedirects(),
3637
)
3738
expect(redirectedPage).toBeDefined()

src/observability/logger/middleware/get-automatic-request-logger.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function getAutomaticRequestLogger() {
3333
const originalEnd = res.end
3434

3535
// Override res.end to log when response completes
36-
res.end = function (chunk?: any, encoding?: any) {
36+
res.end = function (...args: unknown[]) {
3737
const responseTime = Date.now() - startTime
3838
const status = res.statusCode || 200
3939
const contentLength = res.getHeader('content-length') || '-'
@@ -59,7 +59,7 @@ export function getAutomaticRequestLogger() {
5959

6060
// Don't log `/_next/` requests unless LOG_LEVEL is `debug` or higher
6161
if (url?.startsWith('/_next/') && logLevelNum < 3) {
62-
return originalEnd.call(this, chunk, encoding)
62+
return originalEnd.apply(this, args as Parameters<typeof originalEnd>)
6363
}
6464

6565
// Choose color based on status code
@@ -80,7 +80,7 @@ export function getAutomaticRequestLogger() {
8080
}
8181

8282
// Call the original end method to complete the response
83-
return originalEnd.call(this, chunk, encoding)
83+
return originalEnd.apply(this, args as Parameters<typeof originalEnd>)
8484
}
8585

8686
next()

src/search/components/input/SearchContext.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import { createContext, useContext, RefObject, SetStateAction, MutableRefObject
22
import type { AIReference } from '../types'
33
import type { AutocompleteSearchHit, GeneralSearchHit } from '@/search/types'
44

5+
export type TranslationFunction = (
6+
strings: TemplateStringsArray | string,
7+
...values: unknown[]
8+
) => string
9+
510
export interface AutocompleteSearchHitWithUserQuery extends AutocompleteSearchHit {
611
isUserQuery?: boolean
712
}
@@ -29,7 +34,7 @@ export interface AskAIState {
2934
}
3035

3136
export interface SearchContextType {
32-
t: any
37+
t: TranslationFunction
3338
generalSearchOptions: GeneralSearchHitWithOptions[]
3439
aiOptionsWithUserInput: AutocompleteSearchHitWithUserQuery[]
3540
generalSearchResultOnSelect: (selectedOption: GeneralSearchHit) => void

src/search/lib/routes/ai-search-autocomplete-route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export async function aiSearchAutocompleteRoute(req: Request, res: Response) {
1010
// If no query is provided, we want to return the top 5 most popular terms
1111
// This is a special case for AI search autocomplete
1212
// So we use `force` to allow the query to be empty without the usual validation error
13-
const force = {} as any
13+
const force: { query?: string } = {}
1414
if (!req.query.query) {
1515
force.query = ''
1616
}

0 commit comments

Comments
 (0)