fix: resolve TypeScript type errors across codebase

- Add experimentalDecorators support in tsconfig.node.json for TypeORM entities
- Fix mssql module import in order-resolver.ts (static vs dynamic import)
- Extend ISqlType parameter types in sql-server.ts for NVarChar compatibility
- Fix variable naming and type assertions in bip-users-dao.ts
- Add proper type assertions for IPC call results in renderer hooks
  (useAuth, useCleaner, useExtractor, useValidation)
- Add definite assignment assertions in config-manager.ts
This commit is contained in:
Misaka_Company
2026-03-04 14:03:23 +08:00
parent 5497e86b58
commit 88c8c256e2
9 changed files with 118 additions and 61 deletions

View File

@@ -147,8 +147,8 @@ function validateEditableFields(settings: Partial<SettingsData>): {
*/
export class ConfigManager {
private static instance: ConfigManager | null = null
private envPath: string
private backupPath: string
private envPath!: string
private backupPath!: string
private configCache: Map<string, string> = new Map()
private initialized: boolean = false
@@ -214,6 +214,8 @@ export class ConfigManager {
* @param key - Configuration key
* @param defaultValue - Default value if key doesn't exist
*/
public get(key: string): string | undefined
public get(key: string, defaultValue: string): string
public get(key: string, defaultValue?: string): string | undefined {
return this.configCache.get(key) ?? defaultValue
}

View File

@@ -114,7 +114,13 @@ export class SqlServerService implements IDatabaseService {
*/
async queryWithParams(
sqlString: string,
params: Record<string, { value: unknown; type?: sql.ISqlType }>
params: Record<
string,
{
value: unknown
type?: sql.ISqlType | sql.ISqlTypeFactoryWithLength | sql.ISqlTypeWithLength
}
>
): Promise<QueryResult> {
if (!this.pool) {
throw new Error('Not connected to SQL Server. Call connect() first.')

View File

@@ -14,18 +14,10 @@
import type { IDatabaseService } from '../database'
import { SqlServerService } from '../database/sql-server'
import { createLogger } from '../logger'
import sql from 'mssql'
const log = createLogger('OrderResolver')
// Dynamically import mssql for SQL Server parameter types
let mssql: typeof import('mssql') | null = null
async function getMssql() {
if (!mssql) {
mssql = await import('mssql')
}
return mssql
}
/**
* Order mapping result
*/
@@ -251,18 +243,26 @@ export class OrderNumberResolver {
const isSqlServer = this.dbService.type === 'sqlserver'
const tableName = this.getTableName(DB_CONFIG.TABLE_NAME)
log.debug('Resolving production IDs', { count: productionIds.length, dbType: this.dbService.type })
log.debug('Resolving production IDs', {
count: productionIds.length,
dbType: this.dbService.type
})
let result
if (isSqlServer) {
// Use queryWithParams for SQL Server with explicit parameter types
const sql = await getMssql()
const placeholders = productionIds.map((_, idx) => `@p${idx}`).join(', ')
const params: Record<string, { value: string; type: sql.ISqlType }> = {}
const params: Record<
string,
{
value: string
type: sql.ISqlType | sql.ISqlTypeFactoryWithLength | sql.ISqlTypeWithLength
}
> = {}
productionIds.forEach((id, idx) => {
params[`p${idx}`] = { value: id, type: sql.NVarChar }
params[`p${idx}`] = { value: id, type: sql.NVarChar(255) }
})
const query = `
@@ -351,12 +351,17 @@ export class OrderNumberResolver {
if (isSqlServer) {
// Use queryWithParams for SQL Server with explicit parameter types
const sql = await getMssql()
const placeholders = orderNumbers.map((_, idx) => `@p${idx}`).join(', ')
const params: Record<string, { value: string; type: sql.ISqlType }> = {}
const params: Record<
string,
{
value: string
type: sql.ISqlType | sql.ISqlTypeFactoryWithLength | sql.ISqlTypeWithLength
}
> = {}
orderNumbers.forEach((id, idx) => {
params[`p${idx}`] = { value: id, type: sql.NVarChar }
params[`p${idx}`] = { value: id, type: sql.NVarChar(255) }
})
const query = `

View File

@@ -121,8 +121,8 @@ export class BIPUsersDAO {
`
const result = await (dbService as SqlServerService).queryWithParams(sqlString, {
username: { value: username, type: sql.NVarChar },
password: { value: password, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) },
password: { value: password, type: sql.NVarChar(255) }
})
if (result.rows.length > 0) {
@@ -177,7 +177,7 @@ export class BIPUsersDAO {
`
const result = await (dbService as SqlServerService).queryWithParams(sqlString, {
computerName: { value: computerName, type: sql.NVarChar }
computerName: { value: computerName, type: sql.NVarChar(255) }
})
if (result.rows.length > 0) {
@@ -265,49 +265,55 @@ export class BIPUsersDAO {
const tableName = this.getTableName()
if (this.dbType === 'sqlserver') {
let sql: string
let params: Record<string, { value: unknown; type?: sql.ISqlType }>
let sqlString: string
let params: Record<
string,
{
value: unknown
type?: sql.ISqlType | sql.ISqlTypeFactoryWithLength | sql.ISqlTypeWithLength
}
>
if (computerName) {
sql = `
sqlString = `
INSERT INTO ${tableName}
(UserName, Password, UserType, ComputerNmae)
VALUES (@username, @password, @userType, @computerName)
`
params = {
username: { value: username, type: sql.NVarChar },
password: { value: password, type: sql.NVarChar },
userType: { value: userType, type: sql.NVarChar },
computerName: { value: computerName, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) },
password: { value: password, type: sql.NVarChar(255) },
userType: { value: userType, type: sql.NVarChar(255) },
computerName: { value: computerName, type: sql.NVarChar(255) }
}
} else {
sql = `
sqlString = `
INSERT INTO ${tableName}
(UserName, Password, UserType)
VALUES (@username, @password, @userType)
`
params = {
username: { value: username, type: sql.NVarChar },
password: { value: password, type: sql.NVarChar },
userType: { value: userType, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) },
password: { value: password, type: sql.NVarChar(255) },
userType: { value: userType, type: sql.NVarChar(255) }
}
}
await (dbService as SqlServerService).queryWithParams(sqlString, params)
return true
} else {
let sql: string
let params: any[]
let sqlString: string
let params: unknown[]
if (computerName) {
sql = `
sqlString = `
INSERT INTO ${tableName}
(UserName, Password, UserType, ComputerNmae)
VALUES (?, ?, ?, ?)
`
params = [username, password, userType, computerName]
} else {
sql = `
sqlString = `
INSERT INTO ${tableName}
(UserName, Password, UserType)
VALUES (?, ?, ?)
@@ -343,8 +349,8 @@ export class BIPUsersDAO {
`
await (dbService as SqlServerService).queryWithParams(sqlString, {
username: { value: username, type: sql.NVarChar },
userType: { value: userType, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) },
userType: { value: userType, type: sql.NVarChar(255) }
})
return true
} else {
@@ -382,8 +388,8 @@ export class BIPUsersDAO {
`
await (dbService as SqlServerService).queryWithParams(sqlString, {
username: { value: username, type: sql.NVarChar },
newPassword: { value: newPassword, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) },
newPassword: { value: newPassword, type: sql.NVarChar(255) }
})
return true
} else {
@@ -419,7 +425,7 @@ export class BIPUsersDAO {
`
await (dbService as SqlServerService).queryWithParams(sqlString, {
username: { value: username, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) }
})
return true
} else {
@@ -455,7 +461,7 @@ export class BIPUsersDAO {
`
const result = await (dbService as SqlServerService).queryWithParams(sqlString, {
username: { value: username, type: sql.NVarChar }
username: { value: username, type: sql.NVarChar(255) }
})
return result.rows.length > 0 && (result.rows[0].count as number) > 0
} else {

View File

@@ -53,7 +53,11 @@ export function useAuth(): UseAuthReturn {
setState((prev) => ({ ...prev, loading: true, error: null }))
try {
const result = await window.electron.ipcRenderer.invoke('auth:login', credentials)
const result = (await window.electron.ipcRenderer.invoke('auth:login', credentials)) as {
success: boolean
userInfo?: UserInfo
error?: string
}
if (result.success && result.userInfo) {
setState({
@@ -85,7 +89,12 @@ export function useAuth(): UseAuthReturn {
setState((prev) => ({ ...prev, loading: true, error: null }))
try {
const result = await window.electron.ipcRenderer.invoke('auth:silentLogin')
const result = (await window.electron.ipcRenderer.invoke('auth:silentLogin')) as {
success: boolean
userInfo?: UserInfo
error?: string
requiresUserSelection?: boolean
}
if (result.success && result.userInfo) {
setState({
@@ -126,14 +135,18 @@ export function useAuth(): UseAuthReturn {
const getCurrentUser = useCallback(async (): Promise<UserInfo | null> => {
try {
const result = await window.electron.ipcRenderer.invoke('auth:getCurrentUser')
const result = (await window.electron.ipcRenderer.invoke('auth:getCurrentUser')) as {
isAuthenticated: boolean
userInfo?: UserInfo
}
if (result.isAuthenticated && result.userInfo) {
const userInfo = result.userInfo
setState((prev) => ({
...prev,
user: result.userInfo,
user: userInfo,
isAuthenticated: true
}))
return result.userInfo
return userInfo
}
return null
} catch {
@@ -143,7 +156,7 @@ export function useAuth(): UseAuthReturn {
const getAllUsers = useCallback(async (): Promise<UserInfo[]> => {
try {
return await window.electron.ipcRenderer.invoke('auth:getAllUsers')
return (await window.electron.ipcRenderer.invoke('auth:getAllUsers')) as UserInfo[]
} catch {
return []
}
@@ -153,7 +166,11 @@ export function useAuth(): UseAuthReturn {
setState((prev) => ({ ...prev, loading: true, error: null }))
try {
const result = await window.electron.ipcRenderer.invoke('auth:switchUser', userInfo)
const result = (await window.electron.ipcRenderer.invoke('auth:switchUser', userInfo)) as {
success: boolean
userInfo?: UserInfo
error?: string
}
if (result.success && result.userInfo) {
setState({
@@ -180,7 +197,7 @@ export function useAuth(): UseAuthReturn {
const isAdmin = useCallback(async (): Promise<boolean> => {
try {
return await window.electron.ipcRenderer.invoke('auth:isAdmin')
return (await window.electron.ipcRenderer.invoke('auth:isAdmin')) as boolean
} catch {
return false
}

View File

@@ -44,9 +44,13 @@ export function useCleaner(): UseCleanerReturn {
setState({ loading: true, data: null, error: null })
try {
const result = await window.electron.ipcRenderer.invoke('cleaner:run', input)
const result = (await window.electron.ipcRenderer.invoke('cleaner:run', input)) as {
success: boolean
data?: CleanerResult
error?: string
}
if (result.success) {
if (result.success && result.data) {
setState({ loading: false, data: result.data, error: null })
return result.data
} else {

View File

@@ -43,9 +43,13 @@ export function useExtractor(): UseExtractorReturn {
setState({ loading: true, data: null, error: null })
try {
const result = await window.electron.ipcRenderer.invoke('extractor:run', input)
const result = (await window.electron.ipcRenderer.invoke('extractor:run', input)) as {
success: boolean
data?: ExtractorResult
error?: string
}
if (result.success) {
if (result.success && result.data) {
setState({ loading: false, data: result.data, error: null })
return result.data
} else {

View File

@@ -68,13 +68,18 @@ export function useValidation(): UseValidationReturn {
setState((prev) => ({ ...prev, loading: true, error: null }))
try {
const result = await window.electron.ipcRenderer.invoke('validation:validate', request)
const result = (await window.electron.ipcRenderer.invoke(
'validation:validate',
request
)) as ValidationResponse
if (result.success) {
const results = result.results || null
const stats = result.stats || null
setState({
loading: false,
data: result.results || null,
stats: result.stats || null,
data: results,
stats: stats,
error: null
})
return result
@@ -105,7 +110,9 @@ export function useValidation(): UseValidationReturn {
const getSharedProductionIds = useCallback(async (): Promise<string[]> => {
try {
const result = await window.electron.ipcRenderer.invoke('validation:getSharedProductionIds')
const result = (await window.electron.ipcRenderer.invoke(
'validation:getSharedProductionIds'
)) as { productionIds?: string[] }
return result?.productionIds || []
} catch {
return []
@@ -117,7 +124,11 @@ export function useValidation(): UseValidationReturn {
materialCodes: string[]
} | null> => {
try {
const result = await window.electron.ipcRenderer.invoke('validation:getCleanerData')
const result = (await window.electron.ipcRenderer.invoke('validation:getCleanerData')) as {
success: boolean
orderNumbers?: string[]
materialCodes?: string[]
}
if (result.success) {
return {
orderNumbers: result.orderNumbers || [],

View File

@@ -15,6 +15,8 @@
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}