'Is not assignable' 使用泛型进行排序时出现类型错误

'Is not assignable' Type error using generic for sorting

复制于此: https://codesandbox.io/s/distracted-sea-uu3l8?file=/src/BoxBox.tsx

我已经精简了它,我认为这个错误接近于我在完整代码中得到的错误。我正在使用 mui 排序 example 但是当调用通用 getComparator 时出现错误 rows.slice().sort(getComparator(order, orderBy)).

错误:参数类型为“(a: { [x: string]: string | number | Date; }, b: { [x: string]: string | number | Date; }) => number”不可分配给类型为“(a: Bob, b: Bob) => number”的参数。 参数类型 'a' 和 'a' 不兼容。 类型 'Bob' 不可分配给类型 '{ [x: string]: string |编号 |日期; }'。 'Bob'.ts(2345)

类型中缺少索引签名
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

type Order = 'asc' | 'desc';

function getComparator<Key extends keyof any>(
  order: Order,
  orderBy: Key,
): (
    a: { [key in Key]: number | string | Date },
    b: { [key in Key]: number | string | Date },
  ) => number {
  return order === 'desc'
    ? (a, b) => descendingComparator(a, b, orderBy)
    : (a, b) => -descendingComparator(a, b, orderBy);
}

当然它不会让你在你的代码中很难看到问题 ...恕我直言,请将其视为建设性批评...

错误是因为 getComparator 得到了两个 { [key in Key]: number | string | Date } 类型的参数,但另一方面 descendingComparator 收到了两个 T 类型的参数,换句话说 T !== { [key in Key]: number | string | Date }

import React, { FC, useState } from "react";
import "./styles.css";
import Box from "@material-ui/core/Box";
import Paper from "@material-ui/core/Paper";

function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

type Order = "asc" | "desc";

function getComparator<Key extends keyof Bob>(
  order: Order,
  orderBy: Key
): (a: Bob, b: Bob) => number {
  return order === "desc"
    ? (a, b) => descendingComparator(a, b, orderBy)
    : (a, b) => -descendingComparator(a, b, orderBy);
}

interface Bob {
  aDate: Date;
  bDate: Date;
  status: string;
  cDate: Date;
  cost: number;
  costId: number;
  personId: number | null;
  itemAmount: number | null;
  notes: string;
}

function createData(
  aDate: Date,
  bDate: Date,
  status: string,
  cDate: Date,
  cost: number,
  costId: number,
  personId: number | null,
  itemAmount: number | null,
  notes: string
): Bob {
  return {
    aDate,
    bDate,
    status,
    cDate,
    cost,
    costId,
    personId,
    itemAmount,
    notes
  };
}

const stuff = [
  createData(
    new Date("2018-05-01"),
    new Date("2018-05-31"),
    "rfds",
    new Date("2018-05-01"),
    20.4,
    24703,
    null,
    0,
    "fdls;akj"
  ),
  createData(
    new Date("2018-05-01"),
    new Date("2018-05-31"),
    "gfaer",
    new Date("2018-05-01"),
    20.4,
    24703,
    null,
    0,
    "fdls;akj"
  )
];

const BobBox: FC = () => {
  const [orderBy, setOrderBy] = useState<keyof Bob>("Status");
  const [order, setOrder] = useState<Order>("asc");

  return (
    <Box component={Paper}>
      {stuff
        .slice()
        .sort(getComparator(order, orderBy))
        .map((item, i) => (
          <Box key={i}>{item.status}</Box>
        ))}
    </Box>
  );
};

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <BobBox />
    </div>
  );
}