繁体   English   中英

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

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

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

来自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)

对象内的数据:

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
}

虽然类型保护给您一个简单的回答yesno的问题:该unknown[]类型实际上是否是您的IXlsxData[] 断言 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
}
  • 我知道更好的方法: 输入 assertion 您可能会承担责任,如果您完全确定除了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