Type 'File | null' is not assignable to type 'File'. in angular 11
Asked Answered
D

6

8

Hi I am new to Angular and currently I am working with Angular 11 project and there I have to upload a CSV file and extract the records of the file in client side and save them in the database via ASP.NET Web API.

Here I followed a tutorial and tried to get the data of the CSV file in angular side and display them in the same page.

Then I got this error,

Type 'File | null' is not assignable to type 'File'. Type 'null' is not assignable to type 'File'.ts(2322)

I tried so many things but still couldn't solve this. Could you please help me?

This is my .ts file,

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styles: [
  ]
})
export class FileUploadComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

  lines: any = [];
  linesR: any = [];

  changeListener(files: FileList) {
    console.log(files);
    if (files && files.length > 0) {
      let file: File = files.item(0);
      console.log(file.name);
      console.log(file.size);
      console.log(file.type);

      let reader: FileReader = new FileReader();
      reader.readAsText(file);
      reader.onload = (e) => {
        let csv: any = reader.result;
        let allTextLines = [];
        allTextLines = csv.split(/\r|\n|\r/);

        let headers = allTextLines[0].split(';');
        let data = headers;
        let tarr = [];
        for (let j = 0; j < headers.length; j++) {
          tarr.push(data[j]);
        }
        this.lines.push(tarr);
        let tarrR = [];
        let arrl = allTextLines.length;
        let rows = [];
        for (let i = 1; i < arrl; i++) {
          rows.push(allTextLines[i].split(';'));
        }
        for (let j = 0; j < arrl; j++) {
          tarrR.push(rows[j]);
        }
        this.linesR.push(tarrR);
      }
    }
  }
}

This is my .html file

    <div class="container">
    <h1 style="text-align: center"> File Upload </h1>
    <br><br>

    <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)">

    <table class="table table-bordered table-dark">
        <thead>
            <tr>
                <th *ngFor="let item of lines[0]; let i = index">
                    {{item}}
                </th>
            </tr>
        </thead>
        <tbody>
            <tr *ngFor="let item of linesR[0]; let i = index">
                <td *ngFor="let itemm of lines[0]; let j = index">
                    {{item[j]}}
                </td>
            </tr>
        </tbody>
    </table>
</div>

This is the error I got

Thank you!

Deoxidize answered 1/2, 2021 at 7:39 Comment(1)
Change your method like following changeListener(files: File[]).Parliamentarian
P
3

Try Using:

fileupload.component.ts

import { Component, OnInit, VERSION } from "@angular/core";
    
@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styles: []
})
export class FileUploadComponent implements OnInit {
      name = "Angular " + VERSION.major;
    
      lines: any = [];
      linesR: any = [];
    
      ngOnInit() {}
    
      changeListener(files) {
        let fileList = (<HTMLInputElement>files.target).files;
        if (fileList && fileList.length > 0) {
          let file: File = fileList[0];
          console.log(file.name);
          console.log(file.size);
          console.log(file.type);
    
          let reader: FileReader = new FileReader();
          reader.readAsText(file);
          reader.onload = e => {
            let csv: any = reader.result;
            let allTextLines = [];
            allTextLines = csv.split(/\r|\n|\r/);
    
            let headers = allTextLines[0].split(";");
            let data = headers;
            let tarr = [];
            for (let j = 0; j < headers.length; j++) {
              tarr.push(data[j]);
            }
            this.lines.push(tarr);
            let tarrR = [];
            let arrl = allTextLines.length;
            let rows = [];
            for (let i = 1; i < arrl; i++) {
              rows.push(allTextLines[i].split(";"));
            }
            for (let j = 0; j < arrl; j++) {
              tarrR.push(rows[j]);
            }
            this.linesR.push(tarrR);
          };
        }
      }
    }

fileupload.component.html

<div class="container">
  <h1 style="text-align: center">File Upload</h1>
  <br /><br />

  <input
    class="form-control"
    type="file"
    class="upload"
    (change)="changeListener($event)"
  />

  <table class="table table-bordered table-dark">
    <thead>
      <tr>
        <th *ngFor="let item of lines[0]; let i = index">
          {{item}}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let item of linesR[0]; let i = index">
        <td *ngFor="let itemm of lines[0]; let j = index">
          {{item[j]}}
        </td>
      </tr>
    </tbody>
  </table>
</div>
Parliamentarian answered 1/2, 2021 at 7:55 Comment(6)
Hi Msk, thank you so much. I tried your answer like this, changeListener(files: File[]) { // const file: File | undefined = files?.item(0); console.log(files); console.log(files[0]); var file: File = files[0]; //if (file && files.length > 0) { if (files && files.length > 0) { let file: File = files.item(0); console.log(file.name); console.log(file.size); console.log(file.type); and now I am getting this error, Property 'item' does not exist on type 'File[]'. let file: File = files.item(0); Could you please help me?Deoxidize
you can get the file with files[0]Parliamentarian
I have updated the answer .get the file from files array as follows let file: File = files[0]; not use files.item(0)Parliamentarian
Hi I tried your answer. Now I am getting errors in .html file like this, Object is possibly 'null'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)"> Property 'files' does not exist on type 'EventTarget'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)">Deoxidize
try this stackblitz example, stackblitz.com/edit/…Parliamentarian
I have implemented you code on the stackblitz it's working now. you can check in the following stackblitz url: stackblitz.com/edit/angular-ivy-bmzpqj?file=src/app/…Parliamentarian
M
3

Another solution is like -

let file: File | any = null;

OR

let file: File | null = null;
Moriarty answered 2/2, 2022 at 10:37 Comment(0)
D
1

You are using strict: true with typescript. That's good! The issue you are facing though is that this piece:

let file: File = files.item(0);

can return undefined, even though you check for the length before. This would make the type File | null , but you are stating it should just be File.

Better would be to change it to the following:

changeListener(files: FileList) {
 const file: File | null = files?.item(0);

 if (file) {
   // here `file` will have type `File` because it has been asserted with the `if`
      console.log(file.size);
      console.log(file.type);

      let reader: FileReader = new FileReader();
      reader.readAsText(file);
      reader.onload = (e) => {
  //...
 
Dalrymple answered 1/2, 2021 at 8:0 Comment(2)
Hi Poul thank you so much. I tried your answer like this, changeListener(files: FileList) { const file: File | undefined = files?.item(0); console.log(files); if (file && files.length > 0) { //if (files && files.length > 0) { //let file: File = files.item(0); console.log(file.name); console.log(file.size); console.log(file.type); and now I am getting this error. Type 'File | null' is not assignable to type 'File | undefined'. Type 'null' is not assignable to type 'File | undefined'.ts(2322) Could you please help me?Deoxidize
@kalpana Correct, if item does not exist, it will return null instead of undefined. I've updated my answerDalrymple
R
1

If you are sure about that you will have values into files item then you can say :

let file: File = files.item(0) as File;
Rescind answered 1/2, 2021 at 9:8 Comment(1)
Hi thanks I tried it and now it is giving this error, error TS2531: Object is possibly 'null'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)"> error TS2339: Property 'files' does not exist on type 'EventTarget'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)">Deoxidize
K
1

If u want to make a file Null do this file= new File([],''); It will reinitialize the file object to an empty file object

Kreiker answered 4/3, 2022 at 16:49 Comment(0)
R
0

I've got no problem with this:

const file = files.item(0);
if (file && file !== null) {
  ...

and this:

const file: any = files.item(0);
if (file && file !== null) {
  ...

And even if I'm using files[0] instead of files.item(0). And all this in strict mode.

Respect answered 1/2, 2021 at 9:15 Comment(2)
Hi thanks I tried it and now it's giving this error, Object is possibly 'null'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)"> Property 'files' does not exist on type 'EventTarget'. <input class="form-control" type="file" class="upload" (change)="changeListener($event.target.files)">Deoxidize
I've updated my answer. Now I see another problem in your error: Property 'files' does not exist on type 'EventTarget'. You can and you MUST solve that one before you can fix the item(0) thing. Maybe try files: Event instead of just files in the parameters section.Respect

© 2022 - 2024 — McMap. All rights reserved.