我无法定义类型以在变量 React.useState 中设置对象数组



我正在尝试使用SheetJS库设置来自.xlsx的值。下面我将介绍代码和错误,以及我尝试过的表格。

var dataToJson的数据输出:

(6) [{…}, {…}, {…}, {…}, {…}, {…}]
0: {idSeller: 503, idSupplier: 20, financialGoal: 0, positivationGoal: 300, qtVenda: 0, …}
1: {idSeller: 3113, idSupplier: 9, financialGoal: 400000, positivationGoal: 6, qtVenda: 0, …}
2: {idSeller: 7303, idSupplier: 378, financialGoal: 390000, positivationGoal: 0, qtVenda: 0, …}
3: {idSeller: 3113, idSupplier: 964, financialGoal: 360000, positivationGoal: 0, qtVenda: 0, …}
4: {idSeller: 7116, idSupplier: 378, financialGoal: 310000, positivationGoal: 0, qtVenda: 0, …}
5: {idSeller: 7117, idSupplier: 378, financialGoal: 300000, positivationGoal: 0, qtVenda: 0, …}
length: 6
__proto__: Array(0)

对象内部的数据:

5:
financialGoal: 300000
idSeller: 7117
idSupplier: 378
positivationGoal: 0
qtVenda: 0
__rowNum__: 6
__proto__: Object

接口和代码:

interface IXlsxData {
financialGoal: number;
idSeller: number;
idSupplier: number;
positivationGoal: number;
qtVenda: number;
// __rowNum__: number;
};

const Archive: React.FC = () => {
const [files, setFiles] = useState<IXlsxData>(null);

const readExcel = (e) => {
e.preventDefault();

var file = e.target.files[0];
var reader = new FileReader();
reader.readAsArrayBuffer(file);

reader.onload = (e) => {
/* Parse data */
let data = e.target.result;
let readedData = XLSX.read(data, {type: 'buffer'});

/* Get first ws (worksheet) */
const wsname = readedData.SheetNames[0];
const ws = readedData.Sheets[wsname];
/* Convert array to json */
const dataToJson = XLSX.utils.sheet_to_json(ws);
setFiles(dataToJson); // ---- ERROR ----
// setFiles([...files, dataToJson]);
};
}

错误:

const dataToJson: unknown[]
Argument of type 'unknown[]' is not assignable to parameter of type 'SetStateAction<IXlsxData[]>'.
Type 'unknown[]' is not assignable to type 'IXlsxData[]'.
Type '{}' is missing the following properties from type 'IXlsxData': financialGoal, idSeller, idSupplier, positivationGoal, qtVendats(2345)

我已经尝试了几种方法:

interface IXlsxData {
[index: number]: { 
financialGoal: number;
idSeller: number;
idSupplier: number;
positivationGoal: number;
qtVenda: number;
};
}

这个:

interface IXlsxProps extends Array<IXlsxData> {};
const [files, setFiles] = useState<IXlsxProps>([]);

IXlsxData的定义很好:

// you dont have to include ALL the existing fields here
// just the ones you're going to use later in the code
interface IXlsxData {
financialGoal: number;
idSeller: number;
idSupplier: number;
positivationGoal: number;
qtVenda: number;
};

但是,如果您期望这些值的数组(正如我从第一个日志中所猜测的(,您必须这样注释useState

const [files, setFiles] = useState<IXlsxData[]>([]);

现在来谈谈真正的问题。问题是XLSX.utils.sheet_to_json(ws)返回一个类型为unknown[]的值,但您的setFiles期望的是一个类型IXlsxData[]的值。现在有几个选项可以确保编译器从sheet_to_json返回的结果是所需的类型:

  • 类型安全方式:类型保护或断言函数
function isIXlsxData(data: unknown): data is IXlsxData {
return (data != null)
&& (typeof data === 'object')
&& (typeof (data as IXlsxData).financialGoal === 'number')
&& (typeof (data as IXlsxData).idSeller === 'number')
&& (typeof (data as IXlsxData).idSupplier === 'number')
&& (typeof (data as IXlsxData).positivationGoal === 'number')
&& (typeof (data as IXlsxData).qtVenda === 'number');
}
function isArrayOfIXlsxData(data: unknown): data is IXlsxData[] {
if (!Array.isArray(data)) return false;

return data.every(isIXlsxData);
}
const dataToJson = XLSX.utils.sheet_to_json(ws);
if (isArrayOfIXlsxData(dataToJson)) {
setFiles(dataToJson);
} else {
// handle error
}

而type guard为您提供了一个简单的答案yesno来回答这个问题:unknown[]类型实际上是否是您的IXlsxData[]。断言功能可能会为您提供更多关于到底出了什么问题的信息:

function assertIXlsxData(data: unknown): asserts data is IXlsxData {
if (data == null) {
throw new Error('IXlsxData assert failed: value is null');
}
if (typeof data !== 'object')
throw new Error('IXlsxData assert failed: value is not an object');
const errors: string[] = [];
(['financialGoal', 
'idSeller', 
'idSupplier', 
'positivationGoal', 
'qtVenda',
] as const).forEach((prop) => {
if (typeof (data as IXlsxData)[prop] !== 'number') {
errors.push(`property ${prop} must be a number`);
}
})
if (errors.length > 0) 
throw new Error(`IXlsxData assert failed: ${errors.join(', ')}`)
}
function assertArrayOfIXlsxData(data: unknown): asserts data is IXlsxData[] {
if (!Array.isArray(data)) 
throw new Error('IXlsxData[] assert failed. Data is not an array');

data.forEach(assertIXlsxData);
}
const dataToJson = XLSX.utils.sheet_to_json(ws);
try {
assertArrayOfIXlsxData(dataToJson);
setFiles(dataToJson);
} catch (ex) {
// handle error
}
  • 我知道更好的方法:键入断言。您可能会承担责任,如果您绝对确定除了IXlsxData[]之外没有其他内容来自此sheet_to_json(ws)调用,请迫使编译器相信您:
const dataToJson = XLSX.utils.sheet_to_json(ws) as IXlsxData[];
setFiles(dataToJson);

最新更新