实现一个泛型,它是 TypeScript 中的一个对象

Implement a generic that is an object in TypeScript

我想要一个可以用于所有过滤器的 onFilterChange 辅助函数,这样我就不需要为每个不同的过滤器都键入它,但我被卡住了:

// helper.ts
export function onFilterChange(prevState: Record<string, any>, fieldName: string, value: string, isDelete = false): Record<string, any> {
  const newFilters: Record<string, any> = { ...prevState };

  if (isDelete) {
    delete newFilters[fieldName];
  } else {
    newFilters[fieldName] = value;
  }

  if (fieldName !== 'page' && 'page' in newFilters) {
    newFilters.page = '1';
  }

  return newFilters;
}

// index.tsx
const [filters, setFilters] = React.useState({page: 1, order: 'desc'});
setFilters(prevState => onFilterChange(prevState, 'statuses', '', true)); // error

上面最后一行代码的错误是: 类型 'Record<string, any>' 缺少类型 '{ page: number; 中的以下属性命令:字符串; }':页面,顺序

我也尝试过 T extends Record 但此代码有错误:

newFilters[fieldName] = value;

类型字符串不能用于索引类型 T。

感谢任何指点。谢谢

您可以像这样应用类型断言:

// index.tsx
const [filters, setFilters] = React.useState({page: 1, order: 'desc'});
setFilters(prevState => onFilterChange(prevState, 'statuses', '', true) as typeof prevState); // Ok

的问题在于,如果您断言该类型,您以后将无法访问 filters.statuses 的值。

您必须提前输入 useState

const [filters, setFilters] = React.useState<
  {page: number; order: string; statuses: string}
>({page: 1, order: 'desc'});

并将您的函数更改为通用函数

//Note this generic only extends page, since this is the only
//value we need guranteed, and access directly with the line below
export function onFilterChange<T extends { page: string }>(
  prevState: T,
  fieldName: keyof T,
  value: T[typeof fieldName],
  isDelete = false
): T {
  const newFilters: T = { ...prevState };

  if (isDelete) {
    delete newFilters[fieldName];
  } else {
    newFilters[fieldName] = value;
  }

  if (fieldName !== 'page' && 'page' in newFilters) {
    newFilters.page = '1'; //Here is why T needs to extend {page: string}
  }

  return newFilters;
}

或者,如果您要设置很多字段但不知道它们的类型,您可以使用索引访问器

const [filters, setFilters] = React.useState<{
  page: number;
  order: string;
} & { [index: string]: string }>({page: 1, order: 'desc'});

我们必须在这里使用交集,否则,我们会得到一个错误Property 'page' of type 'number' is not assignable to 'string' index type 'string'.ts(2411)

另请注意,TS 在此处捕获了您已经犯下的错误,其中 page 值是您的 useState 中的数字,但在您的函数中将其重新分配为字符串,我不知道是否是有意还是无意,但是 type/fix 根据需要。