chore(ts): enable noFallthroughCasesInSwitch and noImplicitOverride (#577)
Turn on both compiler checks in the root TypeScript configuration, which apps/web, apps/api, apps/extension, packages/shared and packages/plugin-api extend, and in the separate Expo configuration of apps/mobile. No switch statement falls through today. The 19 members that override a base class member (React error boundaries, the local database recovery error and the vendored poster badge) now declare `override`; this only changes type checking and is erased from the emitted JavaScript.
This commit is contained in:
1 parent
ffff9ac2a1
commit
3e54226110
8 files changed
+23
-19
No files matched your search
@@ -3,6 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"ignoreDeprecations": "6.0",
|
||||
"strict": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
|
||||
@@ -17,7 +17,7 @@ type State = {
|
||||
const isChineseInterface = () => navigator.language.toLowerCase().startsWith("zh");
|
||||
|
||||
export class DesktopRendererErrorBoundary extends React.Component<{ children: ReactNode }, State> {
|
||||
state: State = { error: null, reporting: false };
|
||||
override state: State = { error: null, reporting: false };
|
||||
|
||||
static getDerivedStateFromError(error: unknown): Pick<State, "error"> {
|
||||
const normalized = error instanceof Error ? error : new Error(String(error));
|
||||
@@ -31,7 +31,7 @@ export class DesktopRendererErrorBoundary extends React.Component<{ children: Re
|
||||
};
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
override componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
markRendererRecoveryRequired();
|
||||
const details: RendererErrorDetails = {
|
||||
kind: "react-error",
|
||||
@@ -56,7 +56,7 @@ export class DesktopRendererErrorBoundary extends React.Component<{ children: Re
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
override render() {
|
||||
if (!this.state.error) return this.props.children;
|
||||
const zh = isChineseInterface();
|
||||
const desktop = Boolean(window.edgeeverDesktop?.isAvailable);
|
||||
|
||||
@@ -14,13 +14,13 @@ type State = {
|
||||
const isChineseInterface = () => navigator.language.toLowerCase().startsWith("zh");
|
||||
|
||||
export class EditorPaneErrorBoundary extends React.Component<Props, State> {
|
||||
state: State = { error: null };
|
||||
override state: State = { error: null };
|
||||
|
||||
static getDerivedStateFromError(error: unknown): State {
|
||||
return { error: error instanceof Error ? error : new Error(String(error)) };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
override componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
markRendererRecoveryRequired();
|
||||
const details = {
|
||||
kind: "react-error" as const,
|
||||
@@ -32,7 +32,7 @@ export class EditorPaneErrorBoundary extends React.Component<Props, State> {
|
||||
void window.edgeeverDesktop?.recordRendererError(details).catch(() => undefined);
|
||||
}
|
||||
|
||||
componentDidUpdate(previousProps: Props) {
|
||||
override componentDidUpdate(previousProps: Props) {
|
||||
if (this.state.error && previousProps.resetKey !== this.props.resetKey) {
|
||||
clearRendererRecoveryRequired();
|
||||
this.setState({ error: null });
|
||||
@@ -44,7 +44,7 @@ export class EditorPaneErrorBoundary extends React.Component<Props, State> {
|
||||
this.setState({ error: null });
|
||||
};
|
||||
|
||||
render() {
|
||||
override render() {
|
||||
if (!this.state.error) return this.props.children;
|
||||
const zh = isChineseInterface();
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@ type Props = {
|
||||
type State = { failed: boolean };
|
||||
|
||||
export class AiSidebarErrorBoundary extends React.Component<Props, State> {
|
||||
state: State = { failed: false };
|
||||
override state: State = { failed: false };
|
||||
|
||||
static getDerivedStateFromError(): State {
|
||||
return { failed: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
override componentDidCatch(error: Error, info: ErrorInfo) {
|
||||
console.error("Caught AI sidebar error", error, info.componentStack);
|
||||
}
|
||||
|
||||
render() {
|
||||
override render() {
|
||||
if (!this.state.failed) return this.props.children;
|
||||
if (!this.props.open) return null;
|
||||
const zh = navigator.language.toLowerCase().startsWith("zh");
|
||||
|
||||
@@ -9,7 +9,7 @@ class LocalDatabaseOperationTimeoutError extends Error {
|
||||
}
|
||||
|
||||
export class LocalDatabaseUnavailableError extends Error {
|
||||
readonly cause: unknown;
|
||||
override readonly cause: unknown;
|
||||
|
||||
constructor(cause: unknown) {
|
||||
super("Browser local storage is not responding");
|
||||
|
||||
+5
-5
@@ -21,20 +21,20 @@ export function measureLabel(text: string, size: number, weight: string, family:
|
||||
}
|
||||
|
||||
export class BadgeBox extends Textbox {
|
||||
static type = 'BadgeBox';
|
||||
static customProperties = ['badgeBg', 'padX', 'padY', 'radius'];
|
||||
static override type = 'BadgeBox';
|
||||
static override customProperties = ['badgeBg', 'padX', 'padY', 'radius'];
|
||||
declare badgeBg: string; declare padX: number; declare padY: number; declare radius: number;
|
||||
constructor(text: string, options?: Partial<TextboxProps> & Partial<BadgeProps>) { super(text, { badgeBg: '#111111', padX: 0.6, padY: 0.34, radius: 0.5, editable: false, lineHeight: 1, ...options } as Partial<TextboxProps>); }
|
||||
private metrics(): Metrics { return measureLabel(this.text.trim(), this.fontSize, String(this.fontWeight), this.fontFamily); }
|
||||
/** Size comes from the measured label, not from Fabric's line layout. */
|
||||
initDimensions(): void {
|
||||
override initDimensions(): void {
|
||||
const m = this.metrics(); const px = this.padX * this.fontSize, py = this.padY * this.fontSize;
|
||||
this.width = m.width + px * 2; this.height = m.ascent + m.descent + py * 2;
|
||||
this.textLines = [this.text]; this._textLines = [[...this.text]]; this.dirty = true;
|
||||
}
|
||||
/** The pill is the visible extent. Fabric's own line cache is never filled here, so its version would throw. */
|
||||
getLineWidth(): number { return this.width; }
|
||||
_render(c: CanvasRenderingContext2D): void {
|
||||
override getLineWidth(): number { return this.width; }
|
||||
override _render(c: CanvasRenderingContext2D): void {
|
||||
const w = this.width, h = this.height; const m = this.metrics(); const r = Math.min(h / 2, this.radius * h);
|
||||
c.save(); c.fillStyle = this.badgeBg; c.beginPath();
|
||||
c.moveTo(-w / 2 + r, -h / 2); c.arcTo(w / 2, -h / 2, w / 2, h / 2, r); c.arcTo(w / 2, h / 2, -w / 2, h / 2, r); c.arcTo(-w / 2, h / 2, -w / 2, -h / 2, r); c.arcTo(-w / 2, -h / 2, w / 2, -h / 2, r); c.closePath(); c.fill();
|
||||
|
||||
@@ -38,17 +38,17 @@ const returnToPreviousPage = () => {
|
||||
};
|
||||
|
||||
class MobileEditorErrorBoundary extends React.Component<React.PropsWithChildren, MobileEditorErrorBoundaryState> {
|
||||
state: MobileEditorErrorBoundaryState = { failed: false };
|
||||
override state: MobileEditorErrorBoundaryState = { failed: false };
|
||||
|
||||
static getDerivedStateFromError(): MobileEditorErrorBoundaryState {
|
||||
return { failed: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error) {
|
||||
override componentDidCatch(error: Error) {
|
||||
console.error("Mobile editor crashed", error);
|
||||
}
|
||||
|
||||
render() {
|
||||
override render() {
|
||||
if (!this.state.failed) return this.props.children;
|
||||
const english = (getBrowserLocale() ?? defaultLocale) === "en-US";
|
||||
return (
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"ignoreDeprecations": "6.0",
|
||||
|
||||
Reference in new issue
Block a user