refactor(fe): eliminate every explicit any; enforce no-explicit-any (R7 S3a·4)
Removes all 13 remaining `any`s and flips the ESLint rule from off to error so new ones can't creep back: - api.ts prefs/data JSON bags: Record<string, any> -> Record<string, unknown>, narrowed at consumers (App language guard; NotificationsPanel shapes the notification `data` per type behind its existing typeof guards) - catch (e: any) -> catch (e) + `e instanceof HttpError` narrowing (SettingsPanel, SetupWizard, PlexPlayer) - the YouTube IFrame API boundary: new lib/youtube.ts types (YTPlayer/ YTPlayerEvent/YTNamespace + a Window augmentation) replace the 6 player anys; tsc surfaced the exact method surface to declare - NotificationsPanel `t` props: any-options -> i18next TFunction Gate green: typecheck (app+node+e2e), eslint 0 errors (rule now enforced), prettier, 74 vitest.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// Minimal typings for the YouTube IFrame Player API surface this app actually uses. The API is
|
||||
// loaded at runtime from youtube.com/iframe_api and ships no official npm types; rather than pull in
|
||||
// @types/youtube we declare just the methods/events PlayerModal calls, so tsc flags any new call
|
||||
// that isn't covered here. See [[reference-yt-iframe-api-remote-control-map]] for what's driveable.
|
||||
|
||||
export interface YTVideoData {
|
||||
title: string;
|
||||
author: string;
|
||||
video_id?: string;
|
||||
}
|
||||
|
||||
export interface YTPlayer {
|
||||
getPlayerState(): number;
|
||||
getCurrentTime(): number;
|
||||
getDuration(): number;
|
||||
getVideoData(): YTVideoData;
|
||||
getIframe(): HTMLIFrameElement;
|
||||
getVolume(): number;
|
||||
isMuted(): boolean;
|
||||
setVolume(volume: number): void;
|
||||
mute(): void;
|
||||
unMute(): void;
|
||||
playVideo(): void;
|
||||
pauseVideo(): void;
|
||||
loadVideoById(opts: { videoId: string; startSeconds?: number }): void;
|
||||
seekTo(seconds: number, allowSeekAhead: boolean): void;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
// The IFrame API fires events carrying a numeric `data` — a player-state code (onStateChange) or an
|
||||
// error code (onError).
|
||||
export interface YTPlayerEvent {
|
||||
data: number;
|
||||
target: YTPlayer;
|
||||
}
|
||||
|
||||
export interface YTPlayerOptions {
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
videoId?: string;
|
||||
playerVars?: Record<string, string | number | undefined>;
|
||||
events?: {
|
||||
onReady?: (e: YTPlayerEvent) => void;
|
||||
onStateChange?: (e: YTPlayerEvent) => void;
|
||||
onError?: (e: YTPlayerEvent) => void;
|
||||
};
|
||||
}
|
||||
|
||||
export interface YTNamespace {
|
||||
Player: new (el: HTMLElement, opts: YTPlayerOptions) => YTPlayer;
|
||||
}
|
||||
|
||||
// The globals the IFrame API script installs on `window` once loaded.
|
||||
declare global {
|
||||
interface Window {
|
||||
YT?: YTNamespace;
|
||||
onYouTubeIframeAPIReady?: () => void;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user