Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4e04c0e
fix: products type mismatches
sylwia-werner Oct 23, 2025
ed55166
refactor: remove unused order related modules
sylwia-werner Oct 23, 2025
7e681e7
Merge branch 'test' into fix/mm2-1362/typescript-errors-pt-4
sylwia-werner Oct 24, 2025
bbc61f1
fix: order module type mismatches
sylwia-werner Oct 26, 2025
a1623aa
refactor: separate order timeline component for readability
sylwia-werner Oct 26, 2025
5d9716e
refactor: remove rest of unused order module files
sylwia-werner Oct 26, 2025
b85094e
refactor: remove console log
sylwia-werner Oct 26, 2025
97cf92a
refactor: remove console log
sylwia-werner Oct 26, 2025
9719ac8
Merge branch 'fix/mm2-1280/typescript-errors-pt-2' into fix/mm2-1318/…
sylwia-werner Oct 26, 2025
1f094fe
fix: minor ts mismatches
sylwia-werner Oct 27, 2025
a837146
fix: PR fixes
sylwia-werner Oct 29, 2025
cb3741e
fix: PR fixes
sylwia-werner Oct 29, 2025
a18176d
fix: PR fixes
sylwia-werner Nov 3, 2025
65db38e
fix: PR fixes
sylwia-werner Nov 3, 2025
93499c3
fix: PR fixes
sylwia-werner Nov 3, 2025
540958d
Merge branch 'fix/mm2-1280/typescript-errors-pt-2' into fix/mm2-1318/…
sylwia-werner Nov 3, 2025
dea7923
fix: PR conflicts, move types from extended-product to products
sylwia-werner Nov 3, 2025
06ba9cf
Merge branch 'test' into fix/mm2-1318/typescript-errors-pt-3
sylwia-werner Nov 3, 2025
71ecb73
Merge branch 'fix/mm2-1318/typescript-errors-pt-3' into fix/mm2-1362/…
sylwia-werner Nov 3, 2025
7da0d41
refactor: customer group tables, flatten the data
sylwia-werner Nov 4, 2025
b763e5f
fix: PR fixes, refactor
sylwia-werner Nov 4, 2025
c0f181d
fix: PR fixes, fix rest of ts issues
sylwia-werner Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
522 changes: 522 additions & 0 deletions # Fix TypeScript Errors - Strategic Plan.md

Large diffs are not rendered by default.

455 changes: 455 additions & 0 deletions fix-typescript-errors-v2.plan.md

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"i18n:validate": "node ./scripts/i18n/validate-translation.js",
"i18n:schema": "node ./scripts/i18n/generate-schema.js",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"format": "prettier --write ."
"format": "prettier --write .",
"ts-check": "node ./scripts/ts-check.js > ts-errors.log 2>&1 && echo 'TypeScript check complete. Results saved to ts-errors.log'",
"typecheck": "tsc --noEmit"
},
"main": "dist/app.js",
"module": "dist/app.mjs",
Expand Down Expand Up @@ -84,6 +86,7 @@
"@medusajs/admin-vite-plugin": "^2.5.0",
"@medusajs/types": "^2.5.0",
"@medusajs/ui-preset": "^2.5.0",
"@types/lodash": "^4.17.20",
"@types/node": "^20.11.15",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
Expand Down
87 changes: 87 additions & 0 deletions scripts/ts-check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// scripts/ts-check.js
// Scans src/**/*.{ts,tsx} and uses tsconfig.json compilerOptions (so JSX settings are respected).

const ts = require("typescript")
const glob = require("glob")
const path = require("path")

// 1) Collect files under /src
const files = glob.sync("src/**/*.{ts,tsx}", { absolute: true })

if (files.length === 0) {
console.log("No TypeScript files found under /src.")
process.exit(0)
}

// 2) Try to find and parse tsconfig.json to reuse compilerOptions (important for JSX)
let compilerOptions = {}
const configPath = ts.findConfigFile(
process.cwd(),
ts.sys.fileExists,
"tsconfig.json"
)

if (configPath) {
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, ts.sys)
if (parsed && parsed.options) {
compilerOptions = parsed.options
} else {
console.warn(
"Warning: Couldn't fully parse tsconfig.json — falling back to defaults."
)
}
} else {
console.warn("Warning: No tsconfig.json found. Using sensible defaults.")
}

// 3) Ensure we don't emit and skip noisy lib checks
compilerOptions = Object.assign({}, compilerOptions, {
noEmit: true,
skipLibCheck: true,
})

// 4) Create program with the explicit file list (so we ignore tsconfig includes/excludes)
const program = ts.createProgram(files, compilerOptions)

// 5) Collect diagnostics
const diagnostics = ts.getPreEmitDiagnostics(program)

if (diagnostics.length === 0) {
console.log(`✅ No TypeScript errors found in ${files.length} files.`)
process.exit(0)
}

// 6) Print diagnostics in "file:line:col - error TS..." form and collect stats
let errorCount = 0
const filesWithErrors = new Set()

diagnostics.forEach((diag) => {
if (diag.file) {
const { line, character } = diag.file.getLineAndCharacterOfPosition(
diag.start
)
const message = ts.flattenDiagnosticMessageText(diag.messageText, "\n")
const relativeFile = path.relative(process.cwd(), diag.file.fileName)

console.log(
`${relativeFile}:${line + 1}:${character + 1} - error TS${diag.code}: ${message}`
)

errorCount++
filesWithErrors.add(relativeFile)
} else {
// global/unbound diagnostic
console.log(
`error TS${diag.code}: ${ts.flattenDiagnosticMessageText(diag.messageText, "\n")}`
)
errorCount++
}
})

// 7) Summary
console.log("\n--- TypeScript Check Summary ---")
console.log(`Scanned files: ${files.length}`)
console.log(`Files with errors: ${filesWithErrors.size}`)
console.log(`Total errors: ${errorCount}`)

process.exit(0)
8 changes: 5 additions & 3 deletions src/components/search/use-search-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ const transformMap: TransformMap = {
},
}

function transformDynamicSearchResults<T extends { count: number }>(
function transformDynamicSearchResults<T extends { count?: number }>(
type: SearchArea,
limit: number,
t: TFunction,
Expand All @@ -737,11 +737,13 @@ function transformDynamicSearchResults<T extends { count: number }>(
return undefined
}

const count = response.count ?? 0

return {
title: t(`app.search.groups.${type}`),
area: type,
hasMore: response.count > limit,
count: response.count,
hasMore: count > limit,
count,
items: data.map(transform),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { useState } from "react"
import { useTranslation } from "react-i18next"
import { useSearchParams } from "react-router-dom"


export type DataTableOrderByKey<TData> = {
key: keyof TData
key: keyof TData | (string & Record<never, never>)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO those nevers should be removed
I tried something more strict but looks horrible
key: keyof TData | keyof TData[keyof TData][keyof TData[keyof TData]]

or

type NestedKeys = keyof T | keyof T[keyof T][keyof T[keyof T]]

export type DataTableOrderByKey = {
key: keyof TData | NestedKeys
label: string
}

another proposed by (AI)an

type NestedKeys = {
[K in keyof T]: T[K] extends object
? ${string & K}.${string & keyof T[K]}
: never
}[keyof T]

export type DataTableOrderByKey = {
key: keyof TData | NestedKeys
label: string
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My version kept autocomplete, will take a look at yours 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left it as it was: key: keyof TData

I flattened the data before passing it to the table, problem solved

label: string
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useTranslation } from "react-i18next"

import { PlaceholderCell } from "../../common/placeholder-cell"
import { HttpTypes } from "@medusajs/types"
import { ExtendedAdminProductVariant } from "../../../../../types/extended-product"

type VariantCellProps = {
variants?: HttpTypes.AdminProductVariant[] | null
variants?: ExtendedAdminProductVariant[] | null
}

export const VariantCell = ({ variants }: VariantCellProps) => {
Expand Down
38 changes: 25 additions & 13 deletions src/extensions/forms/form-extension-zone/form-extension-zone.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { InlineTip, Input, Switch } from "@medusajs/ui"
import { ComponentType } from "react"
import { ControllerRenderProps, UseFormReturn } from "react-hook-form"
import { ControllerRenderProps, FieldPath, FieldValues, UseFormReturn } from "react-hook-form"
import { useTranslation } from "react-i18next"
import { Form } from "../../../components/common/form"
import { FormField } from "../../types"
import { FormFieldType } from "./types"
import { getFieldType } from "./utils"

type FormExtensionZoneProps = {
type FormExtensionZoneProps<TFieldValues extends FieldValues = FieldValues> = {
fields: FormField[]
form: UseFormReturn<any>
form: UseFormReturn<TFieldValues>
}

export const FormExtensionZone = ({ fields, form }: FormExtensionZoneProps) => {
export const FormExtensionZone = <TFieldValues extends FieldValues = FieldValues>({
fields,
form
}: FormExtensionZoneProps<TFieldValues>) => {
return (
<div>
{fields.map((field, index) => (
Expand All @@ -33,12 +36,15 @@ function getFieldLabel(field: FormField) {
.join(" ")
}

type FormExtensionFieldProps = {
type FormExtensionFieldProps<TFieldValues extends FieldValues = FieldValues> = {
field: FormField
form: UseFormReturn<any>
form: UseFormReturn<TFieldValues>
}

const FormExtensionField = ({ field, form }: FormExtensionFieldProps) => {
const FormExtensionField = <TFieldValues extends FieldValues = FieldValues>({
field,
form
}: FormExtensionFieldProps<TFieldValues>) => {
const label = getFieldLabel(field)
const description = field.description
const placeholder = field.placeholder
Expand All @@ -51,7 +57,7 @@ const FormExtensionField = ({ field, form }: FormExtensionFieldProps) => {
return (
<Form.Field
control={control}
name={`additional_data.${field.name}`}
name={`additional_data.${field.name}` as FieldPath<TFieldValues>}
render={({ field }) => {
return (
<Form.Item>
Expand All @@ -73,19 +79,25 @@ const FormExtensionField = ({ field, form }: FormExtensionFieldProps) => {
)
}

type FormExtensionFieldComponentProps = {
field: ControllerRenderProps
type FormExtensionFieldComponentProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
field: ControllerRenderProps<TFieldValues, TName>
type: FormFieldType
component?: ComponentType<any>
component?: ComponentType<ControllerRenderProps<TFieldValues, TName> & { placeholder?: string }>
placeholder?: string
}

const FormExtensionFieldComponent = ({
const FormExtensionFieldComponent = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({
field,
type,
component,
placeholder,
}: FormExtensionFieldComponentProps) => {
}: FormExtensionFieldComponentProps<TFieldValues, TName>) => {
const { t } = useTranslation()

if (component) {
Expand Down
Loading