mirror of
https://github.com/apache/superset.git
synced 2026-05-12 19:35:17 +00:00
fix(types): fix TypeScript errors in controls and filters
- Revert DatasourceControlProps to required props and add proper TestProps interface in tests - Fix AdhocFilterOptionProps interface to match actual callback signatures - Add optional chaining for onChange callbacks in AdhocFilterControl - Fix AdhocFilter class type casting for translateToSql compatibility - Add @ts-expect-error for propTypes/defaultProps assignments 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -73,8 +73,39 @@ const mockDatasource: TestDatasource = {
|
||||
sql: 'SELECT * FROM mock_datasource_sql',
|
||||
};
|
||||
|
||||
interface TestProps {
|
||||
hovered: boolean;
|
||||
type: string;
|
||||
label: string;
|
||||
default: null;
|
||||
description: null;
|
||||
value: string;
|
||||
form_data: JsonObject;
|
||||
datasource: TestDatasource;
|
||||
validationErrors: string[];
|
||||
name: string;
|
||||
actions: {
|
||||
changeDatasource: jest.Mock;
|
||||
setControlValue: jest.Mock;
|
||||
};
|
||||
isEditable: boolean;
|
||||
user: {
|
||||
createdOn: string;
|
||||
email: string;
|
||||
firstName: string;
|
||||
isActive: boolean;
|
||||
lastName: string;
|
||||
permissions: JsonObject;
|
||||
roles: JsonObject;
|
||||
userId: number;
|
||||
username: string;
|
||||
};
|
||||
onChange: jest.Mock;
|
||||
onDatasourceSave: jest.Mock;
|
||||
}
|
||||
|
||||
// Use type assertion for test props since the component is wrapped with withTheme
|
||||
const createProps = (overrides: JsonObject = {}): Record<string, unknown> => ({
|
||||
const createProps = (overrides: JsonObject = {}): TestProps => ({
|
||||
hovered: false,
|
||||
type: 'DatasourceControl',
|
||||
label: 'Datasource',
|
||||
|
||||
@@ -82,15 +82,15 @@ interface FormData {
|
||||
}
|
||||
|
||||
interface DatasourceControlProps {
|
||||
actions?: DatasourceControlActions;
|
||||
actions: DatasourceControlActions;
|
||||
onChange?: () => void;
|
||||
value?: string | null;
|
||||
datasource?: ExtendedDatasource;
|
||||
datasource: ExtendedDatasource;
|
||||
form_data?: FormData;
|
||||
isEditable?: boolean;
|
||||
onDatasourceSave?: ((datasource: ExtendedDatasource) => void) | null;
|
||||
theme?: SupersetTheme;
|
||||
user?: User;
|
||||
theme: SupersetTheme;
|
||||
user: User;
|
||||
// ControlHeader-related props
|
||||
hovered?: boolean;
|
||||
type?: string;
|
||||
@@ -99,8 +99,6 @@ interface DatasourceControlProps {
|
||||
description?: string | null;
|
||||
validationErrors?: string[];
|
||||
name?: string;
|
||||
// Allow additional props
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface DatasourceControlState {
|
||||
|
||||
@@ -77,7 +77,8 @@ export default class AdhocFilter {
|
||||
this.sqlExpression =
|
||||
typeof adhocFilter.sqlExpression === 'string'
|
||||
? adhocFilter.sqlExpression
|
||||
: translateToSql(adhocFilter, { useSimple: true });
|
||||
// Cast to unknown first to handle type mismatch between AdhocFilterInput and AdhocFilter from @superset-ui/core
|
||||
: translateToSql(adhocFilter as unknown as Parameters<typeof translateToSql>[0], { useSimple: true });
|
||||
this.clause = adhocFilter.clause;
|
||||
if (
|
||||
adhocFilter.operator &&
|
||||
@@ -106,12 +107,24 @@ export default class AdhocFilter {
|
||||
}
|
||||
|
||||
duplicateWith(nextFields: Partial<AdhocFilterInput>): AdhocFilter {
|
||||
return new AdhocFilter({
|
||||
...this,
|
||||
// all duplicated fields are not new (i.e. will not open popup automatically)
|
||||
isNew: false,
|
||||
// Spread class properties as plain object for constructor input
|
||||
const currentFields: AdhocFilterInput = {
|
||||
expressionType: this.expressionType,
|
||||
subject: this.subject,
|
||||
operator: this.operator,
|
||||
operatorId: this.operatorId,
|
||||
comparator: this.comparator,
|
||||
clause: this.clause,
|
||||
sqlExpression: this.sqlExpression,
|
||||
isExtra: this.isExtra,
|
||||
isNew: false, // all duplicated fields are not new
|
||||
datasourceWarning: this.datasourceWarning,
|
||||
deck_slices: this.deck_slices,
|
||||
layerFilterScope: this.layerFilterScope,
|
||||
filterOptionName: this.filterOptionName,
|
||||
...nextFields,
|
||||
});
|
||||
};
|
||||
return new AdhocFilter(currentFields);
|
||||
}
|
||||
|
||||
equals(adhocFilter: AdhocFilter): boolean {
|
||||
@@ -163,6 +176,7 @@ export default class AdhocFilter {
|
||||
}
|
||||
|
||||
translateToSql(): string {
|
||||
return translateToSql(this);
|
||||
// Cast to unknown first to handle type mismatch between class and @superset-ui/core AdhocFilter type
|
||||
return translateToSql(this as unknown as Parameters<typeof translateToSql>[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ class AdhocFilterControl extends Component<AdhocFilterControlProps, AdhocFilterC
|
||||
this.onRemoveFilter(index);
|
||||
}}
|
||||
onMoveLabel={this.moveLabel}
|
||||
onDropLabel={() => this.props.onChange(this.state.values)}
|
||||
onDropLabel={() => this.props.onChange?.(this.state.values)}
|
||||
partitionColumn={this.state.partitionColumn}
|
||||
/>
|
||||
);
|
||||
@@ -282,7 +282,7 @@ class AdhocFilterControl extends Component<AdhocFilterControlProps, AdhocFilterC
|
||||
...prevState,
|
||||
values: valuesCopy,
|
||||
}));
|
||||
this.props.onChange(valuesCopy);
|
||||
this.props.onChange?.(valuesCopy);
|
||||
}
|
||||
|
||||
onRemoveFilter(index: number): void {
|
||||
@@ -305,14 +305,14 @@ class AdhocFilterControl extends Component<AdhocFilterControlProps, AdhocFilterC
|
||||
values: [...prevState.values, mappedOption],
|
||||
}),
|
||||
() => {
|
||||
this.props.onChange(this.state.values);
|
||||
this.props.onChange?.(this.state.values);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onFilterEdit(changedFilter: AdhocFilter): void {
|
||||
this.props.onChange(
|
||||
this.props.onChange?.(
|
||||
this.state.values.map(value => {
|
||||
if (value.filterOptionName === changedFilter.filterOptionName) {
|
||||
return changedFilter;
|
||||
@@ -325,14 +325,15 @@ class AdhocFilterControl extends Component<AdhocFilterControlProps, AdhocFilterC
|
||||
onChange(opts: FilterOption[] | null): void {
|
||||
const options = (opts || [])
|
||||
.map(option => this.mapOption(option))
|
||||
.filter(option => option);
|
||||
this.props.onChange(options);
|
||||
.filter((option): option is AdhocFilter => option !== null);
|
||||
this.props.onChange?.(options);
|
||||
}
|
||||
|
||||
getMetricExpression(savedMetricName: string): string {
|
||||
return this.props.savedMetrics.find(
|
||||
const metric = this.props.savedMetrics?.find(
|
||||
savedMetric => savedMetric.metric_name === savedMetricName,
|
||||
).expression;
|
||||
);
|
||||
return metric?.expression ?? '';
|
||||
}
|
||||
|
||||
moveLabel(dragIndex: number, hoverIndex: number): void {
|
||||
@@ -429,7 +430,10 @@ class AdhocFilterControl extends Component<AdhocFilterControlProps, AdhocFilterC
|
||||
}
|
||||
}
|
||||
|
||||
// Static properties are defined in the class using static keyword
|
||||
// @ts-expect-error - propTypes are defined for runtime validation but TypeScript handles type checking
|
||||
AdhocFilterControl.propTypes = propTypes;
|
||||
// @ts-expect-error - defaultProps for backward compatibility with PropTypes
|
||||
AdhocFilterControl.defaultProps = defaultProps;
|
||||
|
||||
export default withTheme(AdhocFilterControl);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import type React from 'react';
|
||||
import { OptionControlLabel } from 'src/explore/components/controls/OptionControls';
|
||||
import { DndItemType } from 'src/explore/components/DndItemType';
|
||||
import AdhocFilterPopoverTrigger from 'src/explore/components/controls/FilterControl/AdhocFilterPopoverTrigger';
|
||||
@@ -26,14 +27,14 @@ import { useGetTimeRangeLabel } from '../utils';
|
||||
|
||||
export interface AdhocFilterOptionProps {
|
||||
adhocFilter: AdhocFilter;
|
||||
onFilterEdit: () => void;
|
||||
onRemoveFilter: () => void;
|
||||
onFilterEdit: (editedFilter: AdhocFilter) => void;
|
||||
onRemoveFilter: (e: React.MouseEvent) => void;
|
||||
options: OptionSortType[];
|
||||
sections: string[];
|
||||
operators: Operators[];
|
||||
datasource: Record<string, any>;
|
||||
partitionColumn: string;
|
||||
onMoveLabel: () => void;
|
||||
sections?: string[];
|
||||
operators?: string[];
|
||||
datasource?: Record<string, unknown>;
|
||||
partitionColumn?: string | null;
|
||||
onMoveLabel: (dragIndex: number, hoverIndex: number) => void;
|
||||
onDropLabel: () => void;
|
||||
index: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user