The parameter type string does not match the argument type string | ArrayBuffer

Encountering a TS error in line 15 specifically with e.target.result.

Error message: Argument type string | ArrayBuffer is not assignable to parameter type string  Type ArrayBuffer is not assignable to type string

let fileTag = document.getElementById("filetag"),
    preview = document.getElementById("preview");

fileTag.addEventListener("change", function() {
    changeImage(this);
});

function changeImage(input) {
    let reader;

    if (input.files && input.files[0]) {
        reader = new FileReader();

        reader.onload = function(e) {
            preview.setAttribute('src', e.target.result);
        }

        reader.readAsDataURL(input.files[0]);
    }
}

Include HTML code:

<div class="img-container">
<input type="file" id="filetag">
<img src="" class="profImage" id="preview" alt="profilePic">
</div>

Answer №1

(Irrespective of the actual solution, it is worth considering utilizing URL.createObjectURL instead of changing the File to a data: URI; this approach can help conserve resources by avoiding unnecessary string conversions.)


The issue arises from the fact that type checking operates at a local level.

let preview = document.getElementById("preview");
let reader = new FileReader();

reader.onload = function(e) {
    preview.setAttribute('src', e.target.result);
}

Based on the surrounding context, TypeScript understands that preview is a DOM element, and therefore expects two string arguments for preview.setAttribute. It also recognizes that e.target is a FileReader, which means its property result could be either a string or an ArrayBuffer. The specific type depends on the method previously called on the FileReader, but conveying this information in a type system is complex and unavailable within the event handler. For all TypeScript knows, the event handler might have been triggered after readAsArrayBuffer was executed somewhere distant on the same FileReader object.

Given your superior understanding compared to the type checker, you can utilize a type assertion to confirm that the value is indeed a string:

reader.onload = function(e) {
    preview.setAttribute('src', e.target.result as string);
}

If you prefer not to clutter your code with numerous type assertions, consider encapsulating your code in a more easily typed abstraction, like so:

function readFileAsDataURL(file): Promise<string> {
    return new Promise((accept, reject) => {
        const reader = new FileReader();
        reader.onload = function (ev) {
            accept(ev.target.result as string);
        };
        /* Note: rejecting with an event is uncommon */
        reader.onabort = reader.onerror = function (ev) {
            reject(ev);
        }
        reader.readAsDataURL(file);
    });
}

async function changeImage(input) {
    preview.setAttribute('src', await readFileAsDataURL(input.files[0]));
}

By consistently using readFileAsDataURL throughout your code instead of directly creating FileReader instances, the need for a type assertion will only exist within that single function.

Answer №2

If you're unsure whether the input will be a string or an ArrayBuffer, you can try this:

function convertArrayBufferToString(buf: ArrayBuffer): string {
    return String.fromCharCode.apply(null, new Uint16Array(buf));
}
// ...
reader.readAsDataURL(typeof input.files[0] === 'string' ? input.files[0] : convertArrayBufferToString(input.files[0]))

Alternatively, if you are certain it will always be a string:

reader.readAsDataURL(input.files[0] as string);

In essence, use the input directly if it's a string, but convert it to a string first if it's an ArrayBuffer. TypeScript might have trouble with this distinction.

https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String

If you're confident it will always be a string, you can simply do:

preview.setAttribute('src', e.target.result as string);

assuming that the input will consistently be a string.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular production application is experiencing issues due to a missing NPM package import

Objective I am aiming to distribute a TypeScript module augmentation of RxJS as an npm package for usage in Angular projects. Challenge While the package functions correctly in local development mode within an Angular application, it fails to import pro ...

An issue arises with getters and setters in TypeScript due to a duplicate identifier error for 'phone_model'

Essentially, my issue revolves around the restriction of not being able to have a property with the same name as used for a getter or setter. For more detailed information on this problem, you can refer to: Duplicate declaration TypeScript Getter Setter. ...

What are some ways I can implement timers and promises from Node 16 into a Typescript application?

The recent Node 16 release introduces a new timers/promises API that has caught my interest. I successfully installed Node 16 using NVM and switched to it: $ nvm use Found '/Users/golergka/Projects/my-project/.nvmrc' with version <16> ...

Utilize Typescript to Invoke Functions of Different Components in Angular 2

Hello everyone, I am a newcomer to Angular 2 and I'm looking to utilize the value of one component in another component. This will help me populate data based on that particular value. In my setup, I have three Components - App.Component, Category.Co ...

Assigning function types to functions that accept generics: A guide

type FormValidationHandler<FormValues> = (params: { formValues: FormValues, debugName?: string, }) => { isValid: boolean, fieldErrors: Record<string, unknown>, formError: string, } const validateForm: FormValidationHandler = param ...

"An error in the signature index results in the failure of the

I'm encountering a coding issue that's puzzling me. The TypeScript index signature I included in my code is as follows: const ships: { [index: string]: Ship } = {}; This snippet of code contains the problematic line: recieveAttack(e: any) { ...

What are the steps for utilizing the watch feature in Vue.js with TypeScript?

Currently, I am looking to convert this JavaScript script into TypeScript. However, I require the syntax for watchers. export default { props: ['branch_id'], watch: {} } ...

Creating a type or interface within a class in TypeScript allows for encapsulation of

I have a situation where I am trying to optimize my code by defining a derivative type inside a generic class in TypeScript. The goal is to avoid writing the derivative type every time, but I keep running into an error. Here is the current version that is ...

"encountered net::ERR_NAME_NOT_RESOLVED error when trying to upload image to s3 storage

I am currently developing an application using Angular. I have been attempting to upload a picture to my S3 bucket, but each time I try, I encounter this error in the console. https://i.stack.imgur.com/qn3AD.png Below is the code snippet from my upload.s ...

Is it possible to expand a section of an Interface in Typescript?

Imagine a scenario where I have two interfaces: // The interface obtained from an external library that cannot be modified interface Balloon { diameter: number; color: "red" | "blue" | "green"; } Now, I want to create my ...

Angular 4 Filtering Pipe: Simplify Data Filtering in Angular

Attempting to replicate AngularJS's OrderBy feature. Working with an array like this, I am aiming to filter the cars by their car category. [ { "car_category": 3, "name": "Fusion", "year": "2010" }, { "car_category": 2, "na ...

The Typescript SyntaxError occurs when attempting to use an import statement outside of a module, typically within a separate file that contains

I am currently developing a Minecraft bot using the mineflayer library from GitHub. To make my code more organized and reusable, I decided to switch to TypeScript and ensure readability in my project structure (see image here: https://i.stack.imgur.com/znX ...

The Typescript error message states: "Unable to access 'add' property of null"

I am trying to implement a role command in discord.js v13.6, but I am facing an issue where it cannot read the line related to adding a role. The error message displayed is Typescript: Cannot read properties of null (reading "add"). How can I resolve thi ...

Trying to retrieve a value from a map in TypeScript and getting the error "map.get is not a function"

I am currently facing an issue with my map implementation where I have strings set as keys and values. However, when attempting to retrieve a value using a key, I encounter an error. Below is the code snippet that I am working with: let map:Map<string, ...

In the past, my code would run smoothly without any issues, but now I am encountering a runtime error even though the code comp

Recently, I started learning TypeScript and encountered an issue while working with Classes. My code was functioning properly before but now it's displaying a runtime error. ...

When utilizing Angular, the mat-datepicker is displayed underneath the modal, even after attempting to modify the z-index

I am encountering a problem with a mat-datepicker displaying below a modal in my Angular application. Here are the key details: Html: <div class="col-12"> <mat-form-field appearance="fill"> <mat-label>Start Date ...

Having trouble getting the onClick function to work in your Next.js/React component?

Recently, I delved into using next-auth for the first time and encountered an issue where my login and logout buttons' onClick functions stopped working when I resumed work on my project the next day. Strangely, nothing is being logged to the console. ...

reconfigure components by resetting settings on a different component

In the interface, I have a section that displays text along with a unique component titled FilterCriteriaList. This component includes custom buttons that alter their color when clicked. My goal is to reset the settings in the FilterCriteriaList component ...

Tips for troubleshooting Angular 4 unit testing using jasmine and karma with simulated HTTP post requests

I have a service that I need to unit test in Angular 4 using TypeScript and Jasmine. The problem is with the http where it needs to perform a post request and get an identity in return, but for some reason, no data is being sent through. My goal is to ac ...

Tips for resolving the ExtPay TypeError when using Typscript and Webpack Bundle

I am currently trying to install ExtPay, a payment library for Chrome Extension, from the following link: https://github.com/Glench/ExtPay. I followed the instructions up until step 3 which involved adding ExtPay to background.js. However, I encountered an ...