Skip to content

Commit 2627c41

Browse files
authored
Remove use of 'any' type in 12 files (#58540)
1 parent 96860a7 commit 2627c41

File tree

14 files changed

+146
-101
lines changed

14 files changed

+146
-101
lines changed

src/app/lib/server-context-utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { extractVersionFromPath } from '@/app/lib/version-utils'
33
import { getUIDataMerged } from '@/data-directory/lib/get-data'
44
import { type LanguageCode } from '@/languages/lib/languages'
55
import { createTranslationFunctions, translate } from '@/languages/lib/translation-utils'
6+
import type { UIStrings } from '@/frame/components/context/MainContext'
67

78
export interface ServerAppRouterContext {
89
currentLanguage: LanguageCode
910
currentVersion: string
1011
sitename: string
11-
site: { data: { ui: any } }
12+
site: { data: { ui: UIStrings } }
1213
}
1314

1415
/**

src/assets/middleware/dynamic-assets.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,11 @@ export default async function dynamicAssets(
144144
assetCacheControl(res)
145145
return res.type('image/webp').send(buffer)
146146
} catch (catchError) {
147-
if (catchError instanceof Error && (catchError as any).code !== 'ENOENT') {
147+
if (
148+
catchError instanceof Error &&
149+
'code' in catchError &&
150+
(catchError as NodeJS.ErrnoException).code !== 'ENOENT'
151+
) {
148152
throw catchError
149153
}
150154
}

src/content-linter/lib/linting-rules/journey-tracks-guide-path-exists.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,26 @@ export const journeyTracksGuidePathExists = {
5252
description: 'Journey track guide paths must reference existing content files',
5353
tags: ['frontmatter', 'journey-tracks'],
5454
function: (params: RuleParams, onError: RuleErrorCallback) => {
55-
// Using any for frontmatter as it's a dynamic YAML object with varying properties
56-
const fm: any = getFrontmatter(params.lines)
57-
if (!fm || !fm.journeyTracks || !Array.isArray(fm.journeyTracks)) return
58-
if (!fm.layout || fm.layout !== 'journey-landing') return
55+
// Using unknown for frontmatter as it's a dynamic YAML object with varying properties
56+
const fm: unknown = getFrontmatter(params.lines)
57+
if (!fm || typeof fm !== 'object' || !('journeyTracks' in fm)) return
58+
const fmObj = fm as Record<string, unknown>
59+
if (!Array.isArray(fmObj.journeyTracks)) return
60+
if (!('layout' in fmObj) || fmObj.layout !== 'journey-landing') return
5961

6062
const journeyTracksLine = params.lines.find((line: string) => line.startsWith('journeyTracks:'))
6163

6264
if (!journeyTracksLine) return
6365

6466
const journeyTracksLineNumber = params.lines.indexOf(journeyTracksLine) + 1
6567

66-
for (let trackIndex = 0; trackIndex < fm.journeyTracks.length; trackIndex++) {
67-
const track: any = fm.journeyTracks[trackIndex]
68-
if (track.guides && Array.isArray(track.guides)) {
69-
for (let guideIndex = 0; guideIndex < track.guides.length; guideIndex++) {
70-
const guide: string = track.guides[guideIndex]
68+
for (let trackIndex = 0; trackIndex < fmObj.journeyTracks.length; trackIndex++) {
69+
const track: unknown = fmObj.journeyTracks[trackIndex]
70+
if (!track || typeof track !== 'object' || !('guides' in track)) continue
71+
const trackObj = track as Record<string, unknown>
72+
if (trackObj.guides && Array.isArray(trackObj.guides)) {
73+
for (let guideIndex = 0; guideIndex < trackObj.guides.length; guideIndex++) {
74+
const guide: string = trackObj.guides[guideIndex]
7175
if (typeof guide === 'string') {
7276
if (!isValidGuidePath(guide, params.name)) {
7377
addError(

src/content-linter/lib/linting-rules/journey-tracks-unique-ids.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ export const journeyTracksUniqueIds = {
1010
tags: ['frontmatter', 'journey-tracks', 'unique-ids'],
1111
function: function GHD060(params: RuleParams, onError: RuleErrorCallback) {
1212
// Using any for frontmatter as it's a dynamic YAML object with varying properties
13-
const fm: any = getFrontmatter(params.lines)
14-
if (!fm || !fm.journeyTracks || !Array.isArray(fm.journeyTracks)) return
15-
if (!fm.layout || fm.layout !== 'journey-landing') return
13+
const fm: unknown = getFrontmatter(params.lines)
14+
if (!fm || typeof fm !== 'object' || !('journeyTracks' in fm)) return
15+
const fmObj = fm as Record<string, unknown>
16+
if (!Array.isArray(fmObj.journeyTracks)) return
17+
if (!('layout' in fmObj) || fmObj.layout !== 'journey-landing') return
1618

1719
// Find the base journeyTracks line
1820
const journeyTracksLine: string | undefined = params.lines.find((line: string) =>
@@ -37,7 +39,7 @@ export const journeyTracksUniqueIds = {
3739
trackCount++
3840

3941
// Stop once we've found all the tracks we know exist
40-
if (fm && fm.journeyTracks && trackCount >= fm.journeyTracks.length) {
42+
if (Array.isArray(fmObj.journeyTracks) && trackCount >= fmObj.journeyTracks.length) {
4143
break
4244
}
4345
}
@@ -48,11 +50,12 @@ export const journeyTracksUniqueIds = {
4850
// Track seen journey track IDs and line number for error reporting
4951
const seenIds = new Map<string, number>()
5052

51-
for (let index = 0; index < fm.journeyTracks.length; index++) {
52-
const track: any = fm.journeyTracks[index]
53-
if (!track || typeof track !== 'object') continue
53+
for (let index = 0; index < fmObj.journeyTracks.length; index++) {
54+
const track: unknown = fmObj.journeyTracks[index]
55+
if (!track || typeof track !== 'object' || !('id' in track)) continue
5456

55-
const trackId = track.id
57+
const trackObj = track as Record<string, unknown>
58+
const trackId = trackObj.id
5659
if (!trackId || typeof trackId !== 'string') continue
5760

5861
const currentLineNumber = getTrackLineNumber(index)

src/content-render/liquid/tool.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,27 @@ export const Tool = {
4747
type: 'block' as const,
4848
tagName: '',
4949
// Liquid template objects don't have TypeScript definitions
50-
templates: [] as any[],
50+
templates: [] as unknown[],
5151

5252
// tagToken and remainTokens are Liquid internal types without TypeScript definitions
53-
parse(tagToken: any, remainTokens: any) {
54-
this.tagName = tagToken.name
53+
parse(tagToken: unknown, remainTokens: unknown) {
54+
const token = tagToken as { name: string; getText: () => string }
55+
this.tagName = token.name
5556
this.templates = []
5657

5758
const stream = this.liquid.parser.parseStream(remainTokens)
5859
stream
5960
.on(`tag:end${this.tagName}`, () => stream.stop())
6061
// tpl is a Liquid template object without TypeScript definitions
61-
.on('template', (tpl: any) => this.templates.push(tpl))
62+
.on('template', (tpl: unknown) => this.templates.push(tpl))
6263
.on('end', () => {
63-
throw new Error(`tag ${tagToken.getText()} not closed`)
64+
throw new Error(`tag ${token.getText()} not closed`)
6465
})
6566
stream.start()
6667
},
6768

6869
// scope is a Liquid scope object, Generator yields/returns Liquid template values - no TypeScript definitions available
69-
*render(scope: any): Generator<any, any, any> {
70+
*render(scope: unknown): Generator<unknown, unknown, unknown> {
7071
const output = yield this.liquid.renderer.renderTemplates(this.templates, scope)
7172
return yield this.liquid.parseAndRender(template, {
7273
tagName: this.tagName,

src/content-render/scripts/all-documents/lib.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Response } from 'express'
22

3-
import type { ExtendedRequest, Page } from '@/types'
3+
import type { ExtendedRequest, Page, Context } from '@/types'
44
import contextualize from '@/frame/middleware/context/context'
55
import features from '@/versions/middleware/features'
66
import shortVersions from '@/versions/middleware/short-versions'
@@ -55,7 +55,7 @@ export async function allDocuments(options: Options): Promise<AllDocument[]> {
5555
const next = () => {}
5656
const res = {}
5757
const pagePath = permalink.href
58-
const context: any = {}
58+
const context: Partial<Context> = {}
5959
const req = {
6060
path: pagePath,
6161
language: permalink.languageCode,
@@ -68,7 +68,7 @@ export async function allDocuments(options: Options): Promise<AllDocument[]> {
6868
await contextualize(req as ExtendedRequest, res as Response, next)
6969
await shortVersions(req as ExtendedRequest, res as Response, next)
7070
req.context.page = page
71-
features(req as any, res as any, next)
71+
features(req as ExtendedRequest, res as Response, next)
7272

7373
const title = fields.includes('title')
7474
? await page.renderProp('title', req.context, { textOnly: true })

src/events/tests/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { contentTypesEnum } from '@/frame/lib/frontmatter'
66
describe('POST /events', () => {
77
vi.setConfig({ testTimeout: 60 * 1000 })
88

9-
async function checkEvent(data: any) {
9+
async function checkEvent(data: unknown) {
1010
if (!Array.isArray(data)) {
1111
data = [data]
1212
}

src/frame/tests/pages.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@ describe('pages module', () => {
6060

6161
// Page objects have dynamic properties from chain/lodash that aren't fully typed
6262
for (const page of englishPages) {
63-
for (const redirect of (page as any).redirect_from) {
64-
for (const version of (page as any).applicableVersions) {
63+
const pageObj = page as Record<string, unknown>
64+
for (const redirect of pageObj.redirect_from as string[]) {
65+
for (const version of pageObj.applicableVersions as string[]) {
6566
const versioned = removeFPTFromPath(path.posix.join('/', version, redirect))
66-
versionedRedirects.push({ path: versioned, file: (page as any).fullPath })
67+
versionedRedirects.push({ path: versioned, file: pageObj.fullPath as string })
6768
if (!redirectToFiles.has(versioned)) {
6869
redirectToFiles.set(versioned, new Set<string>())
6970
}
70-
redirectToFiles.get(versioned)!.add((page as any).fullPath)
71+
redirectToFiles.get(versioned)!.add(pageObj.fullPath as string)
7172
}
7273
}
7374
}
@@ -97,7 +98,7 @@ describe('pages module', () => {
9798
page.languageCode === 'en' && // only check English
9899
!page.relativePath.includes('index.md') && // ignore TOCs
99100
// Page class has dynamic frontmatter properties like 'allowTitleToDifferFromFilename' not in type definition
100-
!(page as any).allowTitleToDifferFromFilename && // ignore docs with override
101+
!(page as Record<string, unknown>).allowTitleToDifferFromFilename && // ignore docs with override
101102
slugger.slug(decode(page.title)) !== path.basename(page.relativePath, '.md') &&
102103
slugger.slug(decode(page.shortTitle || '')) !== path.basename(page.relativePath, '.md')
103104
)
@@ -129,7 +130,7 @@ describe('pages module', () => {
129130
const frontmatterErrors = chain(pages)
130131
// .filter(page => page.languageCode === 'en')
131132
// Page class has dynamic error properties like 'frontmatterErrors' not in type definition
132-
.map((page) => (page as any).frontmatterErrors)
133+
.map((page) => (page as Record<string, unknown>).frontmatterErrors)
133134
.filter(Boolean)
134135
.flatten()
135136
.value()
@@ -149,7 +150,7 @@ describe('pages module', () => {
149150

150151
for (const page of pages) {
151152
// Page class has dynamic properties like 'raw' markdown not in type definition
152-
const markdown = (page as any).raw
153+
const markdown = (page as Record<string, unknown>).raw as string
153154
if (!patterns.hasLiquid.test(markdown)) continue
154155
try {
155156
await liquid.parse(markdown)

src/languages/tests/translation-error-comments.ts

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,20 @@ import {
88
import { TitleFromAutotitleError } from '@/content-render/unified/rewrite-local-links'
99
import Page from '@/frame/lib/page'
1010

11+
// Type aliases for error objects with token information
12+
type ErrorWithToken = Error & { token: { file: string; getPosition: () => number[] } }
13+
type ErrorWithTokenNoFile = Error & { token: { getPosition: () => number[] } }
14+
type ErrorWithTokenNoPosition = Error & { token: { file: string } }
15+
type ErrorWithTokenAndOriginal = Error & {
16+
token: { file: string; getPosition: () => number[] }
17+
originalError: Error
18+
}
19+
1120
describe('Translation Error Comments', () => {
1221
// Mock renderContent for integration tests
13-
let mockRenderContent: MockedFunction<(template: string, context: any) => string>
22+
let mockRenderContent: MockedFunction<
23+
(template: string, context: Record<string, unknown>) => string
24+
>
1425

1526
beforeEach(() => {
1627
mockRenderContent = vi.fn()
@@ -26,7 +37,7 @@ describe('Translation Error Comments', () => {
2637
test('includes all fields when token information is available', () => {
2738
const error = new Error("Unknown tag 'badtag', line:1, col:3")
2839
error.name = 'ParseError'
29-
;(error as any).token = {
40+
;(error as unknown as ErrorWithToken).token = {
3041
file: '/content/test/article.md',
3142
getPosition: () => [1, 3],
3243
}
@@ -48,11 +59,13 @@ describe('Translation Error Comments', () => {
4859
test('includes original error message when available', () => {
4960
const error = new Error("Unknown variable 'variables.nonexistent.value'")
5061
error.name = 'RenderError'
51-
;(error as any).token = {
62+
;(error as unknown as ErrorWithToken).token = {
5263
file: '/content/test/intro.md',
5364
getPosition: () => [3, 15],
5465
}
55-
;(error as any).originalError = new Error('Variable not found: variables.nonexistent.value')
66+
;(error as unknown as ErrorWithTokenAndOriginal).originalError = new Error(
67+
'Variable not found: variables.nonexistent.value',
68+
)
5669

5770
const result = createTranslationFallbackComment(error, 'rawIntro')
5871

@@ -67,7 +80,7 @@ describe('Translation Error Comments', () => {
6780
test('falls back to main error message when no originalError', () => {
6881
const error = new Error('Main error message')
6982
error.name = 'RenderError'
70-
;(error as any).token = {
83+
;(error as unknown as ErrorWithToken).token = {
7184
file: '/content/test.md',
7285
getPosition: () => [1, 1],
7386
}
@@ -82,7 +95,7 @@ describe('Translation Error Comments', () => {
8295
test('includes tokenization error details', () => {
8396
const error = new Error('Unexpected token, line:1, col:10')
8497
error.name = 'TokenizationError'
85-
;(error as any).token = {
98+
;(error as unknown as ErrorWithToken).token = {
8699
file: '/content/test/page.md',
87100
getPosition: () => [1, 10],
88101
}
@@ -152,7 +165,7 @@ describe('Translation Error Comments', () => {
152165
test('handles error with token but no file', () => {
153166
const error = new Error('Error message')
154167
error.name = 'ParseError'
155-
;(error as any).token = {
168+
;(error as unknown as ErrorWithTokenNoFile).token = {
156169
// No file property
157170
getPosition: () => [5, 10],
158171
}
@@ -167,7 +180,7 @@ describe('Translation Error Comments', () => {
167180
test('handles error with token but no getPosition method', () => {
168181
const error = new Error('Error message')
169182
error.name = 'ParseError'
170-
;(error as any).token = {
183+
;(error as unknown as ErrorWithTokenNoPosition).token = {
171184
file: '/content/test.md',
172185
// No getPosition method
173186
}
@@ -246,7 +259,7 @@ describe('Translation Error Comments', () => {
246259
test('comment format is valid HTML', () => {
247260
const error = new Error('Test error')
248261
error.name = 'ParseError'
249-
;(error as any).token = {
262+
;(error as unknown as ErrorWithToken).token = {
250263
file: '/content/test.md',
251264
getPosition: () => [1, 1],
252265
}
@@ -264,7 +277,7 @@ describe('Translation Error Comments', () => {
264277
test('contains all required fields when available', () => {
265278
const error = new Error('Detailed error message')
266279
error.name = 'RenderError'
267-
;(error as any).token = {
280+
;(error as unknown as ErrorWithToken).token = {
268281
file: '/content/detailed-test.md',
269282
getPosition: () => [42, 15],
270283
}
@@ -283,7 +296,7 @@ describe('Translation Error Comments', () => {
283296
test('maintains consistent field order', () => {
284297
const error = new Error('Test message')
285298
error.name = 'ParseError'
286-
;(error as any).token = {
299+
;(error as unknown as ErrorWithToken).token = {
287300
file: '/content/test.md',
288301
getPosition: () => [1, 1],
289302
}
@@ -320,18 +333,20 @@ describe('Translation Error Comments', () => {
320333
}
321334

322335
// Mock renderContent to simulate error for Japanese, success for English
323-
mockRenderContent.mockImplementation((template: string, innerContext: any) => {
324-
if (innerContext.currentLanguage !== 'en' && template.includes('badtag')) {
325-
const error = new Error("Unknown tag 'badtag'")
326-
error.name = 'ParseError'
327-
;(error as any).token = {
328-
file: '/content/test.md',
329-
getPosition: () => [1, 5],
336+
mockRenderContent.mockImplementation(
337+
(template: string, innerContext: Record<string, unknown>) => {
338+
if (innerContext.currentLanguage !== 'en' && template.includes('badtag')) {
339+
const error = new Error("Unknown tag 'badtag'")
340+
error.name = 'ParseError'
341+
;(error as unknown as ErrorWithToken).token = {
342+
file: '/content/test.md',
343+
getPosition: () => [1, 5],
344+
}
345+
throw error
330346
}
331-
throw error
332-
}
333-
return innerContext.currentLanguage === 'en' ? 'English Title' : template
334-
})
347+
return innerContext.currentLanguage === 'en' ? 'English Title' : template
348+
},
349+
)
335350

336351
const result = await renderContentWithFallback(mockPage, 'rawTitle', context)
337352

@@ -357,14 +372,16 @@ describe('Translation Error Comments', () => {
357372
},
358373
}
359374

360-
mockRenderContent.mockImplementation((template: string, innerContext: any) => {
361-
if (innerContext.currentLanguage !== 'en' && template.includes('badtag')) {
362-
const error = new Error("Unknown tag 'badtag'")
363-
error.name = 'ParseError'
364-
throw error
365-
}
366-
return 'English Title'
367-
})
375+
mockRenderContent.mockImplementation(
376+
(template: string, innerContext: Record<string, unknown>) => {
377+
if (innerContext.currentLanguage !== 'en' && template.includes('badtag')) {
378+
const error = new Error("Unknown tag 'badtag'")
379+
error.name = 'ParseError'
380+
throw error
381+
}
382+
return 'English Title'
383+
},
384+
)
368385

369386
const result = await renderContentWithFallback(mockPage, 'rawTitle', context, {
370387
textOnly: true,
@@ -384,7 +401,7 @@ describe('Translation Error Comments', () => {
384401
const failingCallable = async () => {
385402
const error = new Error("Unknown variable 'variables.bad'")
386403
error.name = 'RenderError'
387-
;(error as any).token = {
404+
;(error as unknown as ErrorWithToken).token = {
388405
file: '/content/article.md',
389406
getPosition: () => [10, 20],
390407
}

0 commit comments

Comments
 (0)