New Typescript 1.8.4 build error: " Build: Property 'result' does not exist on type 'EventTarget'. "
Typescripttypescript1.8Typescript Problem Overview
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
Typescript Solutions
Solution 1 - Typescript
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
};
Solution 2 - Typescript
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 {
Solution 3 - Typescript
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;
}
Solution 4 - Typescript
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;
Solution 5 - Typescript
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
Solution 6 - Typescript
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
}
Solution 7 - Typescript
Today this worked for me at TypeScript 2.1.1
interface EventTarget { result: any; }
Solution 8 - Typescript
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
Solution 9 - Typescript
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);
}
Solution 10 - Typescript
instead of
this.localDbRequest.onsuccess = function (event) {
const db = event.target.result;
};
do
this.localDbRequest.onsuccess = function (event) {
const db = this.result;
};
Solution 11 - Typescript
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
Solution 12 - Typescript
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')
};
Solution 13 - Typescript
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.
Solution 14 - Typescript
Try this.
event.target["result"]
Solution 15 - Typescript
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
};