实现一个泛型,它是 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 根据需要。
我想要一个可以用于所有过滤器的 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 根据需要。