我正在尝试使用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为您提供了一个简单的答案yes
或no
来回答这个问题: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);