Skip to content

Commit e0734f8

Browse files
heiskrCopilot
andauthored
Remove no-explicit-any from data-directory get-data accessor (#61675)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c155667 commit e0734f8

8 files changed

Lines changed: 45 additions & 35 deletions

File tree

eslint.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ export default [
238238
'src/article-api/transformers/rest-transformer.ts',
239239
'src/content-linter/scripts/lint-content.ts',
240240
'src/content-render/unified/annotate.ts',
241-
'src/data-directory/lib/get-data.ts',
242241
'src/frame/components/context/MainContext.tsx',
243242
'src/landings/components/CookBookFilter.tsx',
244243
'src/languages/lib/correct-translation-content.ts',

src/content-render/liquid/data.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ export default {
3838
},
3939

4040
async render(scope: CustomScope) {
41-
let text = getDataByLanguage(this.path, scope.environments.currentLanguage || '')
41+
let text = getDataByLanguage(this.path, scope.environments.currentLanguage || '') as
42+
| string
43+
| undefined
4244
if (text === undefined) {
4345
if (scope.environments.currentLanguage === 'en') {
4446
const message = `Can't find the key 'data ${this.path}' in the scope.`

src/content-render/liquid/indented-data-reference.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const IndentedDataReference = {
5151
const text: string | undefined = getDataByLanguage(
5252
dataReference,
5353
scope.environments.currentLanguage,
54-
)
54+
) as string | undefined
5555
if (text === undefined) {
5656
if (scope.environments.currentLanguage === 'en') {
5757
const message = `Can't find the key 'indented_data_reference ${dataReference}' in the scope.`

src/data-directory/lib/get-data.ts

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import { merge, get } from 'lodash-es'
88
import languages from '@/languages/lib/languages-server'
99
import { correctTranslatedContentStrings } from '@/languages/lib/correct-translation-content'
1010
import { createLogger } from '@/observability/logger'
11+
import type { UIStrings } from '@/frame/components/context/MainContext'
1112

1213
const logger = createLogger(import.meta.url)
1314

1415
interface YAMLException extends Error {
15-
mark?: any
16+
mark?: unknown
1617
}
1718

1819
interface FileSystemError extends Error {
@@ -35,7 +36,7 @@ const ALWAYS_ENGLISH_MD_FILES = new Set([
3536

3637
// Returns all the things inside a directory
3738
export const getDeepDataByLanguage = memoize(
38-
(dottedPath: string, langCode: string, dir: string | null = null): any => {
39+
(dottedPath: string, langCode: string, dir: string | null = null): Record<string, unknown> => {
3940
if (!(langCode in languages)) {
4041
throw new Error(`langCode '${langCode}' not a recognized language code`)
4142
}
@@ -53,12 +54,12 @@ export const getDeepDataByLanguage = memoize(
5354

5455
// Doesn't need to be memoized because it's used by getDataKeysByLanguage
5556
// which is already memoized.
56-
function getDeepDataByDir(dottedPath: string, dir: string): any {
57+
function getDeepDataByDir(dottedPath: string, dir: string): Record<string, unknown> {
5758
const fullPath = ['data']
5859
const split = dottedPath.split(/\./g)
5960
fullPath.push(...split)
6061

61-
const things: any = {}
62+
const things: Record<string, unknown> = {}
6263
const relPath = fullPath.join(path.sep)
6364
for (const dirent of getDirents(dir, relPath)) {
6465
if (dirent.name === 'README.md') continue
@@ -81,30 +82,30 @@ function getDirents(root: string, relPath: string): fs.Dirent[] {
8182
return fs.readdirSync(filePath, { withFileTypes: true })
8283
}
8384

84-
export const getUIDataMerged = memoize((langCode: string): any => {
85+
export const getUIDataMerged = memoize((langCode: string): UIStrings => {
8586
const uiEnglish = getUIData('en')
86-
if (langCode === 'en') return uiEnglish
87+
if (langCode === 'en') return uiEnglish as UIStrings
8788
// Got to combine. Start with the English and put the translation on top.
8889
// E.g.
8990
// english = {food: "Food", drink: "Drink"}
9091
// swedish = {food: "Mat"}
9192
// =>
9293
// combind = {food: "Mat", drink: "Drink"}
93-
const combined: any = {}
94+
const combined: Record<string, unknown> = {}
9495
merge(combined, uiEnglish)
9596
merge(combined, getUIData(langCode))
96-
return combined
97+
return combined as UIStrings
9798
})
9899

99100
// Doesn't need to be memoized because it's used by another function
100101
// that is memoized.
101-
const getUIData = (langCode: string): any => {
102+
const getUIData = (langCode: string): Record<string, unknown> => {
102103
const fullPath = ['data', 'ui.yml']
103104
const { dir } = languages[langCode]
104-
return getYamlContent(dir, fullPath.join(path.sep))
105+
return getYamlContent(dir, fullPath.join(path.sep)) as Record<string, unknown>
105106
}
106107

107-
export const getDataByLanguage = memoize((dottedPath: string, langCode: string): any => {
108+
export const getDataByLanguage = memoize((dottedPath: string, langCode: string): unknown => {
108109
if (!(langCode in languages))
109110
throw new Error(`langCode '${langCode}' not a recognized language code`)
110111
const { dir } = languages[langCode]
@@ -151,7 +152,7 @@ function getDataByDir(
151152
dir: string,
152153
englishRoot?: string,
153154
langCode?: string,
154-
): any {
155+
): unknown {
155156
const fullPath = ['data']
156157

157158
// Using English here because it doesn't matter. We just want to
@@ -186,17 +187,23 @@ function getDataByDir(
186187
const basename = split.pop()!
187188
fullPath.push(...split)
188189
fullPath.push(`${basename}.yml`)
189-
const allData = getYamlContent(dir, fullPath.join(path.sep), englishRoot)
190+
const allData = getYamlContent(dir, fullPath.join(path.sep), englishRoot) as
191+
| Record<string, unknown>
192+
| undefined
190193
if (allData && key) {
191194
const value = allData[key]
192195
if (value) {
193-
let content = matter(value).content
196+
let content = matter(value as string).content
194197
if (dir !== englishRoot) {
195198
let englishContent = content
196199
try {
197-
const englishData = getYamlContent(englishRoot, fullPath.join(path.sep), englishRoot)
200+
const englishData = getYamlContent(
201+
englishRoot,
202+
fullPath.join(path.sep),
203+
englishRoot,
204+
) as Record<string, unknown> | undefined
198205
if (englishData?.[key]) {
199-
englishContent = matter(englishData[key]).content
206+
englishContent = matter(englishData[key] as string).content
200207
}
201208
} catch (error) {
202209
if ((error as FileSystemError).code !== 'ENOENT') {
@@ -312,7 +319,7 @@ function getSmartSplit(dottedPath: string): string[] {
312319
// -> cache HIT (Yay!)
313320
//
314321
const getYamlContent = memoize(
315-
(root: string | undefined, relPath: string, englishRoot?: string): any => {
322+
(root: string | undefined, relPath: string, englishRoot?: string): unknown => {
316323
// Certain Yaml files we know we always want the English one
317324
// no matter what the specified language is.
318325
// For example, we never want `data/variables/product.yml` translated
@@ -368,9 +375,11 @@ const getFileContent = (
368375
}
369376
}
370377

371-
function memoize<T extends (...args: any[]) => any>(func: T): T {
372-
const cache = new Map<string, any>()
373-
return ((...args: any[]) => {
378+
function memoize<Args extends unknown[], Return>(
379+
func: (...args: Args) => Return,
380+
): (...args: Args) => Return {
381+
const cache = new Map<string, Return>()
382+
return (...args: Args) => {
374383
if (process.env.NODE_ENV === 'development') {
375384
// It is very possible that certain files, when caching is disabled,
376385
// are read multiple times in short succession. E.g. `product.yml`.
@@ -391,6 +400,6 @@ function memoize<T extends (...args: any[]) => any>(func: T): T {
391400
if (!cache.has(key)) {
392401
cache.set(key, func(...args))
393402
}
394-
return cache.get(key)
395-
}) as T
403+
return cache.get(key) as Return
404+
}
396405
}

src/data-directory/tests/get-data.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,24 +170,24 @@ describe('get-data', () => {
170170
{
171171
const result = getUIDataMerged('en')
172172
expect(result.key).toBe('Value')
173-
expect(result.deep.er).toBe('Depth')
173+
expect((result.deep as Record<string, string>).er).toBe('Depth')
174174
}
175175
// In a specific language
176176
{
177177
const result = getUIDataMerged('ja')
178178
expect(result.key).toBe('価値')
179-
expect(result.deep.er).toBe('深さ')
179+
expect((result.deep as Record<string, string>).er).toBe('深さ')
180180
// Note how it falls back to English on that key
181-
expect(result.deep.est).toBe('Deepest')
181+
expect((result.deep as Record<string, string>).est).toBe('Deepest')
182182
}
183183
})
184184

185185
test('getDeepDataByLanguage', () => {
186186
// The most basic test
187187
{
188188
const result = getDeepDataByLanguage('variables', 'en')
189-
expect(result.stuff.foo).toBe('Foo')
190-
expect(result.stuff.bar).toBe('Bar')
189+
expect((result.stuff as Record<string, string>).foo).toBe('Foo')
190+
expect((result.stuff as Record<string, string>).bar).toBe('Bar')
191191
}
192192
// All reusables
193193
{

src/frame/middleware/context/glossaries.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default async function glossaries(req: ExtendedRequest, res: Response, ne
2525
const enGlossaryMap = new Map()
2626
// But we don't need to bother if the current language is English.
2727
if (req.context.currentLanguage !== 'en') {
28-
const enGlossariesRaw: Glossary[] = getDataByLanguage('glossaries.external', 'en')
28+
const enGlossariesRaw: Glossary[] = getDataByLanguage('glossaries.external', 'en') as Glossary[]
2929

3030
for (const { term, description } of enGlossariesRaw) {
3131
enGlossaryMap.set(term, description)
@@ -40,7 +40,7 @@ export default async function glossaries(req: ExtendedRequest, res: Response, ne
4040
const glossariesRaw: Glossary[] = getDataByLanguage(
4141
'glossaries.external',
4242
req.context.currentLanguage!,
43-
)
43+
) as Glossary[]
4444
const glossariesList = (
4545
await Promise.all(
4646
glossariesRaw.map(async (glossary) => {

src/release-notes/middleware/get-release-notes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getDataByLanguage, getDeepDataByLanguage } from '@/data-directory/lib/get-data'
2-
import type { ReleaseNotes } from '@/types'
2+
import type { GHESReleasePatch, ReleaseNotes } from '@/types'
33

44
// If we one day support release-notes for other products, add it here.
55
// Checking against this is only really to make sure there's no typos
@@ -47,7 +47,7 @@ export function getReleaseNotes(prefix: string, langCode: string) {
4747
const data = getDataByLanguage(
4848
`release-notes.${prefix}.${majorVersion}.${minorVersion}`,
4949
langCode,
50-
)
50+
) as GHESReleasePatch
5151
// A simple but powerful validation. If the `sections:` thing
5252
// is incorrectly translated so it's no longer an array, then we
5353
// don't pick this up from the translation.

src/versions/lib/get-applicable-versions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function getApplicableVersions(
4343
}
4444

4545
if (!featureData) {
46-
featureData = getDeepDataByLanguage('features', 'en')
46+
featureData = getDeepDataByLanguage('features', 'en') as FeatureData
4747
}
4848

4949
// Check for frontmatter that includes a feature name, like:

0 commit comments

Comments
 (0)