In a large project, I have a standard reporting module that displays in a grid data, and where the user can define filters and sorting.
Because I don't want to replicate logic, I setup a generic filtering function that can accept data from any type and filter options.
Everything is working perfectly, but ESlint is yelling because of the any
usage.
Here's a simplified reproductible code (actual code contains a lot more rules and complexity, like string normalization and data sorting):
// In module utility
type reportState = {
filterOn : string,
filterValue : string
}
const filterDataPredicate = (row : any, viewOptions : reportState)=>{
const dataKey = viewOptions.filterOn as keyof any;
const valueToCheck = row[dataKey];
return valueToCheck?.toString() === viewOptions.filterValue;
}
// In consuming module 1
type Point = {
x: number,
y: number
};
const graphData: Point[] = [
{ x: 0, y: 20 }, { x: -8, y: 12 }, { x: 100, y: 0 }
]
const currentGraphReportOptions = {
filterOn : "x",
filterValue : "0"
};
const filteredGraphData = graphData.filter((row)=>filterDataPredicate(row, currentGraphReportOptions));
console.log(filteredGraphData);
// In consuming module 2
type Customer = {
firstName: string,
lastName: string
};
const customerData: Customer[] = [
{ firstName: "John", lastName : "Smith"}, { firstName : "Jane", lastName:"Smith"},{ firstName : "Joe", lastName:"Dalton"}
]
const currentCustomerReportOptions = {
filterOn : "lastName",
filterValue : "Smith"
};
const filteredCustomerData = customerData.filter((row)=>filterDataPredicate(row, currentCustomerReportOptions));
console.log(filteredCustomerData);
Everything works as expected, except for the ESLint warning :
warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
My IDE (VSCode) suggests me to either replace type by unknown
or never
, but none works.
When using unknown
, row[dataKey]
is not compiling (Object is of type 'unknown'.(2571)
), while when using never
, it tells me .toString()
is not available on never
type (Property 'toString' does not exist on type 'never'.(2339)
).
Is there a clean way to fix that?
PS: if it matters, I enable strict : true
in my tsconfig.json file, and in my eslint config I have :
{
"rules": {
"@typescript-eslint/no-explicit-any": "error"
}
}
I managed to fix the issue (w/o disabling the rule)
The correct type for row object should Record<string, unknown>
.
I think this is working because my incoming row will be non empty objects and nothing else (no base type, ...). Whatever the object values will be, it's always identified by an object key.
// In module utility
type reportState = {
filterOn : string,
filterValue : string
}
const filterDataPredicate = (row : Record<string, unknown>, viewOptions : reportState)=>{
const dataKey = viewOptions.filterOn;
const valueToCheck = row[dataKey];
return `${valueToCheck}` === viewOptions.filterValue;
}
// In consuming module 1
type Point = {
x: number,
y: number
};
const graphData: Point[] = [
{ x: 0, y: 20 }, { x: -8, y: 12 }, { x: 100, y: 0 }
]
const currentGraphReportOptions = {
filterOn : "x",
filterValue : "0"
};
const filteredGraphData = graphData.filter((row)=>filterDataPredicate(row, currentGraphReportOptions));
console.log(filteredGraphData);
// In consuming module 2
type Customer = {
firstName: string,
lastName: string
};
const customerData: Customer[] = [
{ firstName: "John", lastName : "Smith"}, { firstName : "Jane", lastName:"Smith"},{ firstName : "Joe", lastName:"Dalton"}
]
const currentCustomerReportOptions = {
filterOn : "lastName",
filterValue : "Smith"
};
const filteredCustomerData = customerData.filter((row)=>filterDataPredicate(row, currentCustomerReportOptions));
console.log(filteredCustomerData);