feat: complete Priority 1 type safety improvements

- Fix remaining any types in test apps (Android, iOS, shared TypeScript)
- Replace non-null assertions with proper null checks
- Improve type safety in EndorserAPIClient and TimeSafariNotificationManager
- Enhanced error handling with explicit null checks

Linting status:  0 errors, 329 warnings (down from 436 warnings)
Priority 1 improvements: 107 warnings fixed (25% reduction)
Type safety: 34 fewer any types, 10 non-null assertions fixed
This commit is contained in:
Matthew Raymer
2025-10-07 07:22:04 +00:00
parent 5e77ba1917
commit 7b4caef5a7
13 changed files with 123 additions and 105 deletions

View File

@@ -62,7 +62,7 @@ export class EndorserAPIClient {
private config: EndorserAPIConfig;
private authToken?: string;
private rateLimiter: Map<string, number> = new Map();
private requestCache: Map<string, { data: any; timestamp: number }> = new Map();
private requestCache: Map<string, { data: unknown; timestamp: number }> = new Map();
constructor(config: Partial<EndorserAPIConfig> = {}) {
this.config = { ...TIMESAFARI_ENDSORER_CONFIG, ...config };
@@ -239,7 +239,9 @@ export class EndorserAPIClient {
undefined
).then(response => {
bundle.offersToPerson = response;
bundle.metadata!.networkResponses++;
if (bundle.metadata) {
bundle.metadata.networkResponses++;
}
})
);
}
@@ -250,7 +252,9 @@ export class EndorserAPIClient {
this.fetchOffersToProjectsOwnedByMe(userConfig.lastKnownOfferId)
.then(response => {
bundle.offersToProjects = response;
bundle.metadata!.networkResponses++;
if (bundle.metadata) {
bundle.metadata.networkResponses++;
}
})
);
}
@@ -264,7 +268,9 @@ export class EndorserAPIClient {
undefined
).then(response => {
bundle.projectUpdates = response;
bundle.metadata!.networkResponses++;
if (bundle.metadata) {
bundle.metadata.networkResponses++;
}
})
);
}
@@ -282,11 +288,17 @@ export class EndorserAPIClient {
bundle.error = error instanceof Error ? error.message : 'Unknown error';
// Ensure we have partial data even on error
bundle.metadata!.networkResponses = bundle.metadata!.networkResponses || 0;
if (bundle.metadata) {
bundle.metadata.networkResponses = bundle.metadata.networkResponses || 0;
}
} finally {
bundle.metadata!.fetchDurationMs = Date.now() - startTime;
console.log(`✅ TimeSafari notification fetch completed in ${bundle.metadata!.fetchDurationMs}ms`);
if (bundle.metadata) {
bundle.metadata.fetchDurationMs = Date.now() - startTime;
}
if (bundle.metadata) {
console.log(`✅ TimeSafari notification fetch completed in ${bundle.metadata.fetchDurationMs}ms`);
}
}
return bundle;
@@ -603,7 +615,7 @@ export class EndorserAPIClient {
/**
* Cache response for future use
*/
private cacheResponse(url: string, data: any): void {
private cacheResponse(url: string, data: unknown): void {
this.requestCache.set(url, {
data,
timestamp: Date.now()
@@ -613,7 +625,7 @@ export class EndorserAPIClient {
/**
* Get cached response if fresh enough
*/
private getCachedResponse(url: string): any {
private getCachedResponse(url: string): unknown {
const cached = this.requestCache.get(url);
if (cached && (Date.now() - cached.timestamp) < 30000) { // 30 seconds cache
return cached.data;

View File

@@ -41,7 +41,7 @@ export interface SecurityConfig {
export interface CryptoOperation {
success: boolean;
data?: any;
data?: Record<string, unknown>;
error?: string;
timestamp: number;
operation: string;
@@ -427,7 +427,7 @@ export class SecurityManager {
/**
* Verify cryptographic signature
*/
private verifySignature(_header: any, _payload: string, signature: string): boolean {
private verifySignature(_header: Record<string, unknown>, _payload: string, signature: string): boolean {
try {
// In a real implementation, this would verify the signature using the public key
// For Phase 4, we'll perform basic signature format validation

View File

@@ -139,7 +139,7 @@ export class TimeSafariNotificationManager {
private apiClient: EndorserAPIClient;
private securityManager: SecurityManager;
private user?: TimeSafariUser;
private cache: Map<string, { data: any; timestamp: number }> = new Map();
private cache: Map<string, { data: unknown; timestamp: number }> = new Map();
private activeGeneration = new Set<string>();
constructor() {
@@ -475,7 +475,10 @@ export class TimeSafariNotificationManager {
notifications: TimeSafariNotificationType[],
timestamp: number
): void {
const cacheKey = `notifications_${this.user!.activeDid}`;
if (!this.user) {
throw new Error('User not initialized');
}
const cacheKey = `notifications_${this.user.activeDid}`;
this.cache.set(cacheKey, {
data: notifications,
timestamp
@@ -486,7 +489,10 @@ export class TimeSafariNotificationManager {
* Get cached notifications if fresh enough
*/
private getCachedNotifications(): TimeSafariNotificationType[] | null {
const cacheKey = `notifications_${this.user!.activeDid}`;
if (!this.user) {
throw new Error('User not initialized');
}
const cacheKey = `notifications_${this.user.activeDid}`;
const cached = this.cache.get(cacheKey);
if (cached && (Date.now() - cached.timestamp) < 300000) { // 5 minutes