ChatGPT解决这个技术问题 Extra ChatGPT

New Typescript 1.8.4 build error: " Build: Property 'result' does not exist on type 'EventTarget'. "

I am New to typescript. In my Durandal application I migrated to VS-2012 to VS-2015 means typescript 0.9 to typescript 1.8.4. After migrated I got so many build errors. I resolved all those except one. I am getting below build error on types of Events.

ERROR: " Build: Property 'result' does not exist on type 'EventTarget' "

And the code was exactly like this below:

var reader:any,
target:EventTarget;

reader= new FileReader();
reader.onload = function (imgsrc){
    var fileUrl = imgsrc.target.result;
}

"Imgsrc" is taking type event.

It's working fine with typescript 0.9 but with 1.8.4 it's throwing error as 'result' does not exist on type 'EventTarget'. Can any one help on this to resolve.

Note: "target:EventTarget" is getting from lib.d.ts


K
KimchiMan

Instead of using event.target.result, you can just use FileReader.result.

For example,

const fileReader: FileReader = new FileReader();

fileReader.onload = (event: Event) => {
   event.target.result; // This is invalid
   fileReader.result; // This is valid
};

can't parse as a json :(
@KimchiMan.. Great ... Can you explain how.?
If this error comes
Type 'string | ArrayBuffer' is not assignable to type 'string'. Type 'ArrayBuffer' is not assignable to type 'string'
> fileReader.result;+'';
this should be the accepted answer, clean and no hacks involved
Actually its ProgressEvent<FileReader> and not just Event...
S
Salketer

While any is a medicine (almost for anything, but... where is the TypeScript benefit then)... there is a similar issue reported and nice (TypesScript-ish) workaround suggested

Request to change currentTarget in Event interface for lib.d.ts

let me cite:

I ran into this TS2339: Property 'result' does not exist on type 'EventTarget' in JS FileReader onload, and another warning for getSummary() on the event passed to FileReader's onerror. My work-around, to suppress the horrid red squiggily lines;-) is the following: interface FileReaderEventTarget extends EventTarget { result:string } interface FileReaderEvent extends Event { target: FileReaderEventTarget; getMessage():string; } Then in my app: reader.onload = function(fre:FileReaderEvent) { var data = JSON.parse(fre.target.result); ... }

And, until some change in lib.d.ts, we still do work with known interface

EDIT Dec 2019:

With this fix, you might be getting

error TS2322: Type '(this: FileReader, e: FileReaderEvent) => void' is not assignable to type '(this: FileReader, ev: ProgressEvent) => any'.

If so, just replace

 interface FileReaderEvent extends Event {

with

 interface FileReaderEvent extends ProgressEvent {

Still unfixed as of late April 2018
Still unfixed as of early June 2018
Still unfixed. October 2018.
still unfixed. Nov 4,2018
Still unfixed as of Jan 2019
R
Rayudu

With my old type script the parameter "imgsrc" is having any type by default.

So, now I made it as (imgsrc:any). It's working fine.

var reader:any,
target:EventTarget;
reader= new FileReader();
reader.onload = function (imgsrc:any){
var fileUrl = imgsrc.target.result;
}

t
tika

The issue is with the typescript definitions. A simple cheat is:

let target: any = e.target; //<-- This (any) will tell compiler to shut up!
let content: string = target.result;

d
dehart

Just let TypScript know what type you would expect it to be.

Here is the fix:

let reader = new FileReader();
reader.onload = function (event){
    let fileUrl = (<FileReader>event.target).result;
}

You could also use reader.result instead in this case


This is the best solution
M
Melroy Fernandes

If anyone is finding the simplest solution then this worked for me.

var reader:any,
target:EventTarget;
reader= new FileReader();
reader.onload = function (imgsrc){
//var fileUrl = imgsrc.target.result; //change to
var fileUrl = (imgsrc.target as FileReader).result; //cast to correct type
}

E
Elcio Mauro Guimarães

Today this worked for me at TypeScript 2.1.1

interface EventTarget { result: any; }

Nice solution, however when I restarted the solution it gives many errors in the lib.d.ts. It collides with the real EventTarget interface.
M
Maravarman Manoharan

If this error comes Type 'string | ArrayBuffer' is not assignable to type 'string'. Type 'ArrayBuffer' is not assignable to type 'string'

fileReader.result+' ';//valid fileReader.result; //invalid


L
Lukas Kurz

I had the same issue in angular with a FileReader.

The solution is rather simple (Typescript has the necessary type). You have to use ProgressEvent<FileReader>. It can be found im lib.dom.d.ts in the typescript installation, so it should be globally availabe if you build with

lib: {
"dom"
}

in your tsconfig.json.

Here is the code where i had to use it:

function read(file: File) {
  const fileReader = new FileReader();
  fileReader.onloadend = function (e: ProgressEvent<FileReader>) {
    const arr = (new Uint8Array(parseInt(e.target.result.toString(), 10))).subarray(0, 4);
    var header = "";
    for (var i = 0; i < arr.length; i++) {
      header += arr[i].toString(16);
    }
    console.log(header);

    // Check the file signature against known types

  };
  fileReader.readAsArrayBuffer(file);
}


D
Dawit

instead of

    this.localDbRequest.onsuccess = function (event) {
      const db = event.target.result;
    };

do

   this.localDbRequest.onsuccess = function (event) {
     const db = this.result;
   };

K
Keegan Cruickshank

The target object can be accessed as below to prevent error until fix:

reader= new FileReader();
reader.onload = function (imgsrc){
    var fileUrl = imgsrc.target["result"];
}

Treating the target as a Javascript Object


K
Katrpilar

The above solutions didn't fit my similar issue with IndexedDB so I thought I'd share what did work in my scenario. By changing the (event) functions' arguments to (event: any) I was able to ignore the type errors.

Sample Code:

let request = window.indexedDB.open('userChannels', 3);

request.onerror = function(event: any ) {
    console.log('ERROR: Failed to create userChannels local DB' + event.target.errorCode)
  };

request.onsuccess = function(event: any) {
   let db = event.target.result;
   console.log('SUCCESS: Created userChannels local DB')
};

M
Michal.S

After lib.dom.d.ts analyzation it is simple:

const fileReader: FileReader = new FileReader();

fileReader.onload = (event: ProgressEvent<FileReader>) => {
   event.target.result; // This is valid
};

G
George Wang

this is a break change of javascript/typescript.

what you will need to do is to just replace "event.target.result" by "this.result".

"this" here refers to the context of interface "MSBaseReader".

below are my implementation excerpt:

      let reader = new FileReader();
      let profile: TransProfile = new TransProfile();

      reader.onload = function(event){
        profile.avatar = new Uint8Array(this.result);
      }

      reader.onerror = function(event){
      }

      this.photoLib.getPhoto(item)
        .then(blob => reader.readAsArrayBuffer(blob))
        .then(() => this.doUpload(profile));

"MSBaseReader" interface definition:

interface MSBaseReader {
    onabort: (this: MSBaseReader, ev: Event) => any;
    onerror: (this: MSBaseReader, ev: ErrorEvent) => any;
    onload: (this: MSBaseReader, ev: Event) => any;
    onloadend: (this: MSBaseReader, ev: ProgressEvent) => any;
    onloadstart: (this: MSBaseReader, ev: Event) => any;
    onprogress: (this: MSBaseReader, ev: ProgressEvent) => any;
    readonly readyState: number;
    readonly result: any;
    abort(): void;
    readonly DONE: number;
    readonly EMPTY: number;
    readonly LOADING: number;
    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}

"FileReader" interface definition

interface FileReader extends EventTarget, MSBaseReader {
    readonly error: DOMError;
    readAsArrayBuffer(blob: Blob): void;
    readAsBinaryString(blob: Blob): void;
    readAsDataURL(blob: Blob): void;
    readAsText(blob: Blob, encoding?: string): void;
    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}

also note that, due to the context change of "this" within "onload()", your class-based definitions are not accessible within "reader.onload = function(event){..."; meaning you can not use "this.class-property" style to address your class properties.

you will have to define local variable. see the definition and usage of "profile" in above excerpt.


Y
YouBee

Try this.

event.target["result"]

While this code may resolve the OP's issue, it is best to include an explanation as to how your code addresses the OP's issue. In this way, future visitors can learn from your post, and apply it to their own code. SO is not a coding service, but a resource for knowledge. Also, high quality, complete answers are more likely to be upvoted. These features, along with the requirement that all posts are self-contained, are some of the strengths of SO as a platform, that differentiates it from forums. You can edit to add additional info &/or to supplement your explanations with source documentation.