GeoffWillis
GeoffWillis

Reputation: 123

How to deal with FileReader returns either ArrayBuffer, or String in TypeScript

I have chased myself in a circle and now time to ask for help. I've got the following (Typescript) service that opens a file reader, and depending upon the file type, calls either readAsText(), or readAsArrayBuffer(). I have a wrapper class (MyDocument) for the text the fileReader will return, as well as some meta data about the doc. In the MyDocument Class, I define a field called docContent: string. This is where the trouble begins. Because of the conditional if statement (Bolded in the code) that picks readAsText or readAsArray buffer, the compiler doesn't like the assignment of the fileReader Results to docConent because it COULD be a string, or ArrayBuffer. So I modify the field to be: docContent: string | ArrayBuffer thinking how clever I am. BUT now that the field can be either a string, or ArrayBuffer, the compiler won't let me manipulate the docContents field (Like split('\n') because split does not belong to ArrayBuffer. I know there must be a more elegant solution to the problem but I'm too close to it to see clearly. Would appreciate any help.

    public readFile(files: FileList): MyDocument {
    this.myDocument = new MyDocument();

    if (files && files[0] && files[0].size > 0) {
        this.fileToRead = files[0];
        this.myDocument.fileName = this.fileToRead.name;
        this.myDocument.fileSize = this.fileToRead.size;
        this.myDocument.fileType = this.fileToRead.type;
    }
    else {
        const message = "Either no file selected, or file has zero size";
        confirm(message);

    }


    if (this.fileToRead) {
        var fr = new FileReader();

        fr.onloadend = () => {
            if (this.myDocument.fileType == "text/plain") {
                this.myDocument.docContents = fr.result;
            } else {
                let extractedText = this.extractTextUsingSolr(fr.result);
            }

        }

        ***if (this.fileToRead.type == 'text/plain') {
            fr.readAsText(this.fileToRead);
        }
        else {
            fr.readAsArrayBuffer(this.fileToRead);
        }***

        return this.myDocument;
    }
    else {
        console.log('No file selected!');
        return;
    }

}

~

Just to be complete, here is the MyDocument class, and when I try to do the docContents.split("\n") that is where the compiler complained.

export class MyDocument {
fileName: string;
fileType: string;
fileSize: number;

numWords: number;
numSents: number;
docWords: string[]; 
docContents: string | ArrayBuffer;

processDocument(): void {
    const sents = [];
    const lines = this.docContents.split("\n");
    let sentWords = [];
    }
}

Upvotes: 2

Views: 1690

Answers (1)

Pavel Kostenko
Pavel Kostenko

Reputation: 1879

quick fix

if (typeof this.docContents === 'string') {
   lines = this.docContents.split("\n");
} else {
  // dealing with ArrayBuffer
  // google on methods in ArrayBuffer object you can use
}

but I personally don't like such approach. I would use 2 different properties with different names. one for ArrayBuffer, another for string of text.

Upvotes: 1

Related Questions