简体   繁体   English

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

[英]I can't define type to set an array of objects in a variable React.useState

I'm trying to set values that come from an.xlsx using the SheetJS library.我正在尝试使用SheetJS库设置来自 an.xlsx 的值。 Below I'll present the codes and error, and soon after the forms I've tried.下面我将介绍代码和错误,以及在我尝试过的 forms 之后不久。

Data output from var dataToJson :来自var dataToJson 的数据 output

(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)

Data inside objects:对象内的数据:

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

Interface and code:接口和代码:

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]);
  };
}

Error:错误:

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)

I've already tried a few ways:我已经尝试了几种方法:

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

and this:和这个:

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

This definition of IXlsxData is fine: 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;
};

But if you're expecting an array of those values (as I can guess by the first log) you have to annotate useState like this:但是,如果您期望这些值的数组(我可以通过第一个日志猜到),则必须像这样注释useState

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

Now to the real problem.现在到了真正的问题。 The problem is XLSX.utils.sheet_to_json(ws) returns a value with type unknown[] but your setFiles is expecting a value with type IXlsxData[] .问题是XLSX.utils.sheet_to_json(ws)返回一个类型为unknown[]的值,但您的setFiles期望一个类型为IXlsxData[]的值。 And now you have several options to ensure the compiler the result returned from sheet_to_json is of the desired type:现在您有几个选项可以确保编译器从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
}

While type guard gives you a simple answer yes or no to the question: whether that unknown[] type is in fact your IXlsxData[] .虽然类型保护给您一个简单的回答yesno的问题:该unknown[]类型实际上是否是您的IXlsxData[] Assertion function may give you more information on what exactly went wrong:断言 function 可能会为您提供有关究竟出了什么问题的更多信息:

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
}
  • I KNOW BETTER way: type assertion .我知道更好的方法: 输入 assertion You may take responsibility and if you're absolutely sure nothing else but IXlsxData[] ever comes from this sheet_to_json(ws) call just force the compiler to believe you:您可能会承担责任,如果您完全确定除了IXlsxData[]没有其他任何东西来自此sheet_to_json(ws)调用,只需强制编译器相信您:
const dataToJson = XLSX.utils.sheet_to_json(ws) as IXlsxData[];
setFiles(dataToJson);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM