访问未知对象成员时如何正确修复'no-implicit-any'?

How to properly fix 'no-implicit-any' when accessing unknown object member?

在一个大型项目中,我有一个标准的报告模块,它显示在网格数据中,用户可以在其中定义过滤器和排序。

因为我不想复制逻辑,所以我设置了一个通用过滤函数,它可以接受来自任何类型和过滤选项的数据。

一切正常,但 ESlint 因 any 用法而大喊大叫。

这是一个简化的 reproductible code(实际代码包含更多规则和复杂性,例如字符串规范化和数据排序):

// 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);

除 ESLint 警告外,一切正常:

warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

我的 IDE (VSCode) 建议我将类型替换为 unknownnever,但 none 有效。

当使用 unknown 时,row[dataKey] 没有编译(Object is of type 'unknown'.(2571)),而当使用 never 时,它告诉我 .toString()never 类型 (Property 'toString' does not exist on type 'never'.(2339)).

有没有一种干净的方法来解决这个问题?

PS:如果重要,我在我的 tsconfig.json 文件中启用 strict : true,并且在我的 eslint 配置中我有:

{
  "rules": {
    "@typescript-eslint/no-explicit-any": "error"
  }
}

您可以将 eslint 规则更改为 "@typescript-eslint/no-explicit-any": "off"。然后它就不会再抱怨了。如果您希望它警告您但不抛出错误,您也可以将其更改为 warning

我设法解决了问题(w/o 禁用规则)

行对象的正确类型应该Record<string, unknown>

我认为这是可行的,因为我的传入行将是非空对象,没有其他任何东西(没有基类型,...)。无论对象值是什么,它始终由对象键标识。

Updated code :

// 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);