chore(translations): enable TypeScript strict mode (#11494)

This commit is contained in:
Germán Jabloñski
2025-03-03 13:01:14 -03:00
committed by GitHub
parent 4ddf96502c
commit a3fe60778c
9 changed files with 43 additions and 32 deletions

View File

@@ -150,7 +150,9 @@ export const importDateFNSLocale = async (locale: string): Promise<Locale> => {
break break
} }
if (result.default) { // @ts-expect-error - I'm not sure if this is still necessary.
if (result?.default) {
// @ts-expect-error - I'm not sure if this is still necessary.
return result.default return result.default
} }

View File

@@ -1,6 +1,7 @@
/* eslint-disable no-console */
import fs from 'fs' import fs from 'fs'
export function copyFile(source, destination) { export function copyFile(source: string, destination: string) {
fs.copyFile(source, destination, (err) => { fs.copyFile(source, destination, (err) => {
if (err) { if (err) {
// Handle error // Handle error

View File

@@ -13,9 +13,12 @@ export function deepMergeSimple<T = object>(obj1: object, obj2: object): T {
for (const key in obj2) { for (const key in obj2) {
if (Object.prototype.hasOwnProperty.call(obj2, key)) { if (Object.prototype.hasOwnProperty.call(obj2, key)) {
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
if (typeof obj2[key] === 'object' && !Array.isArray(obj2[key]) && obj1[key]) { if (typeof obj2[key] === 'object' && !Array.isArray(obj2[key]) && obj1[key]) {
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
output[key] = deepMergeSimple(obj1[key], obj2[key]) output[key] = deepMergeSimple(obj1[key], obj2[key])
} else { } else {
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
output[key] = obj2[key] output[key] = obj2[key]
} }
} }

View File

@@ -1,11 +1,13 @@
import fs from 'fs' import fs from 'fs'
export function ensureDirectoryExists(directory) { export function ensureDirectoryExists(directory: string) {
try { try {
if (!fs.existsSync(directory)) { if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true }) fs.mkdirSync(directory, { recursive: true })
} }
} catch (error) { } catch (error) {
console.error(`Error creating directory '${directory}': ${error.message}`) const msg = error instanceof Error ? error.message : 'Unknown error'
// eslint-disable-next-line no-console
console.error(`Error creating directory '${directory}': ${msg}`)
} }
} }

View File

@@ -14,7 +14,9 @@ export const getTranslation = <T extends LabelType>(
): T extends JSX.Element ? JSX.Element : string => { ): T extends JSX.Element ? JSX.Element : string => {
// If it's a Record, look for translation. If string or React Element, pass through // If it's a Record, look for translation. If string or React Element, pass through
if (typeof label === 'object' && !Object.prototype.hasOwnProperty.call(label, '$$typeof')) { if (typeof label === 'object' && !Object.prototype.hasOwnProperty.call(label, '$$typeof')) {
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
if (label[i18n.language]) { if (label[i18n.language]) {
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
return label[i18n.language] return label[i18n.language]
} }
@@ -25,8 +27,9 @@ export const getTranslation = <T extends LabelType>(
fallbacks = i18n.fallbackLanguage fallbacks = i18n.fallbackLanguage
} }
const fallbackLang = fallbacks.find((language) => label[language]) const fallbackLang = fallbacks.find((language) => label[language as keyof typeof label])
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
return fallbackLang && label[fallbackLang] ? label[fallbackLang] : label[Object.keys(label)[0]] return fallbackLang && label[fallbackLang] ? label[fallbackLang] : label[Object.keys(label)[0]]
} }

View File

@@ -2,8 +2,8 @@ import type { Language } from '../types.js'
import { clientTranslationKeys } from '../clientKeys.js' import { clientTranslationKeys } from '../clientKeys.js'
function filterKeys(obj, parentGroupKey = '', keys) { function filterKeys(obj: Record<string, unknown>, parentGroupKey = '', keys: string[]) {
const result = {} const result: Record<string, unknown> = {}
for (const [namespaceKey, value] of Object.entries(obj)) { for (const [namespaceKey, value] of Object.entries(obj)) {
// Skip $schema key // Skip $schema key
@@ -13,7 +13,7 @@ function filterKeys(obj, parentGroupKey = '', keys) {
} }
if (typeof value === 'object') { if (typeof value === 'object') {
const filteredObject = filterKeys(value, namespaceKey, keys) const filteredObject = filterKeys(value as Record<string, unknown>, namespaceKey, keys)
if (Object.keys(filteredObject).length > 0) { if (Object.keys(filteredObject).length > 0) {
result[namespaceKey] = filteredObject result[namespaceKey] = filteredObject
} }
@@ -40,13 +40,13 @@ function filterKeys(obj, parentGroupKey = '', keys) {
return result return result
} }
function sortObject(obj) { function sortObject(obj: Record<string, unknown>) {
const sortedObject = {} const sortedObject: Record<string, unknown> = {}
Object.keys(obj) Object.keys(obj)
.sort() .sort()
.forEach((key) => { .forEach((key) => {
if (typeof obj[key] === 'object') { if (typeof obj[key] === 'object') {
sortedObject[key] = sortObject(obj[key]) sortedObject[key] = sortObject(obj[key] as Record<string, unknown>)
} else { } else {
sortedObject[key] = obj[key] sortedObject[key] = obj[key]
} }

View File

@@ -145,9 +145,13 @@ export function t<
const initTFunction: InitTFunction = (args) => { const initTFunction: InitTFunction = (args) => {
const { config, language, translations } = args const { config, language, translations } = args
const mergedTranslations = config?.translations?.[language] const mergedTranslations =
? deepMergeSimple<DefaultTranslationsObject>(translations, config?.translations?.[language]) language && config?.translations?.[language as keyof typeof config.translations]
: translations ? deepMergeSimple<DefaultTranslationsObject>(
translations,
config.translations[language as keyof typeof config.translations]!,
)
: translations
return { return {
t: (key, vars) => { t: (key, vars) => {
@@ -161,18 +165,14 @@ const initTFunction: InitTFunction = (args) => {
} }
} }
function memoize( function memoize<T extends Parameters<InitI18n>[0], K extends keyof T>(
fn: (args: Parameters<InitI18n>[0]) => Promise<I18n>, fn: (args: T) => Promise<I18n>,
keys: string[], keys: K[],
): ( ): (args: T) => Promise<I18n> {
args: { const cacheMap = new Map<string, I18n>()
context: 'api' | 'client'
} & Parameters<InitI18n>[0],
) => Promise<I18n> {
const cacheMap = new Map()
const memoized = async (args) => { const memoized = async (args: T) => {
const cacheKey = keys.reduce((acc, key) => acc + args[key], '') const cacheKey = keys.reduce((acc, key) => acc + String(args[key]), '')
if (!cacheMap.has(cacheKey)) { if (!cacheMap.has(cacheKey)) {
const result = await fn(args) const result = await fn(args)
@@ -187,7 +187,11 @@ function memoize(
export const initI18n = memoize( export const initI18n = memoize(
async ({ config, context, language = config.fallbackLanguage }) => { async ({ config, context, language = config.fallbackLanguage }) => {
const translations = getTranslationsByContext(config.supportedLanguages[language], context) if (!language || !config.supportedLanguages?.[language]) {
throw new Error(`Language ${language} not supported`)
}
const translations = getTranslationsByContext(config.supportedLanguages?.[language], context)
const { t, translations: mergedTranslations } = initTFunction({ const { t, translations: mergedTranslations } = initTFunction({
config: config as any, config: config as any,
@@ -202,7 +206,7 @@ export const initI18n = memoize(
const i18n: I18n = { const i18n: I18n = {
dateFNS, dateFNS,
dateFNSKey, dateFNSKey,
fallbackLanguage: config.fallbackLanguage, fallbackLanguage: config.fallbackLanguage!,
language: language || config.fallbackLanguage, language: language || config.fallbackLanguage,
t, t,
translations: mergedTranslations, translations: mergedTranslations,

View File

@@ -152,7 +152,7 @@ function parseAcceptLanguage(acceptLanguageHeader: string): LanguagePreference[]
export function extractHeaderLanguage(acceptLanguageHeader: string): AcceptedLanguages | undefined { export function extractHeaderLanguage(acceptLanguageHeader: string): AcceptedLanguages | undefined {
const parsedHeader = parseAcceptLanguage(acceptLanguageHeader) const parsedHeader = parseAcceptLanguage(acceptLanguageHeader)
let matchedLanguage: AcceptedLanguages let matchedLanguage: AcceptedLanguages | undefined
for (const { language } of parsedHeader) { for (const { language } of parsedHeader) {
if (!matchedLanguage && acceptedLanguages.includes(language)) { if (!matchedLanguage && acceptedLanguages.includes(language)) {

View File

@@ -1,7 +1,3 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": {
/* TODO: remove the following lines */
"strict": false,
}
} }