Flow error: Unable to access the value of this.props.width as the property width is not defined in T

In my React Native project, I am utilizing Flow for type checking.

For more information, visit:

I currently have two files named SvgRenderer.js and Cartoon.js where:

Cartoon extends SvgRenderer

Below is the source code for both of these files:

SvgRenderer.js

import React from 'react';
import Svg, { G } from 'react-native-svg';

export default class SvgRenderer<T> extends React.Component<T> {

  width: number;
  height: number;
  scaleFactor: number;

  constructor(props: T) {
    super(props);
  }
  ...
  config(originalSize: number[]) {
    switch (true) {
      case (this.props.width != undefined):
        this.scaleFactor = this.props.width / originalSize[0];
        this.width = this.props.width;
        this.height = originalSize[1] * this.scaleFactor;
        break;
      case (this.props.height != undefined):
        this.scaleFactor = this.props.height / originalSize[1];
        this.width = originalSize[0] * this.scaleFactor;
        this.height = this.props.height;
        break;
    }
  }
}

Cartoon.js

import React from 'react';
import SvgRenderer from './SvgRenderer';

type Props = {
  for: string,
  width?: number,
  height?: number,
};

export default class Cartoon extends SvgRenderer<Props> {

  firstBorder: string;

  constructor(props: Props) {
    super(props);
  }
  render() {
    return ...
  }
}

My issue arises when executing the command:

$ npm run flow

The error message received is:

Error -------------------- src/helpers/SvgRenderer.js:32:24

Cannot get this.props.width because property width is missing in T [1].

     src/helpers/SvgRenderer.js
     29|     this.originalWidth = originalSize[0];
     30|     this.originalHeight = originalSize[1];
     31|     switch (true) {
     32|       case (this.props.width != undefined):
     33|         this.scaleFactor = this.props.width / this.originalWidth;
     34|         this.width = this.props.width;
     35|         this.height = this.originalHeight * this.scaleFactor;

Error -------------------- src/helpers/SvgRenderer.js:33:39

Cannot get this.props.width because property width is missing in T [1].

     src/helpers/SvgRenderer.js
     30|     this.originalHeight = originalSize[1];
     31|     switch (true) {
     32|       case (this.props.width != undefined):
     33|         this.scaleFactor = this.props.width / this.originalWidth;
     34|         this.width = this.props.width;
     35|         this.height = this.originalHeight * this.scaleFactor;
     36|         break;

An image showing the error can be found here: https://i.stack.imgur.com/C1Hn5.png

The confusion lies in why Flow indicates (for SvgRenderer):

Cannot get this.props.width because property width is missing in T [1].

even though I defined width within Cartoon, as shown below:

type Props = {
  for: string,
  width?: number,
  height?: number,
};

While aware that width and height may be considered types, I require them as such.

Any suggestions on adjusting the code so that Flow deems it acceptable?

Thank you!

Answer №1

In order for the type T to have access to properties width and height, it is important to ensure that the type T actually possesses these properties. This can be achieved by setting constraints for the generic type parameter:

type Dimensions = { width?: number, height?: number };

class SvgRenderer<T: Dimensions> extends React.Component<T> {
  // ...

  config(originalSize: number[]) {
    if (this.props.width != undefined) {
      this.scaleFactor = this.props.width / originalSize[0];
      this.width = this.props.width;
      this.height = originalSize[1] * this.scaleFactor;
      return;
    }

    if (this.props.height != undefined) {
      this.scaleFactor = this.props.height / originalSize[1];
      this.width = originalSize[0] * this.scaleFactor;
      this.height = this.props.height;
    }
  }
}

** It is also important to note the slight change in the config method (using if statements instead of switch/case) - this allows Flow to refine the type of width/height (excluding undefined) so that arithmetic operations like

this.props.width / originalSize[0]
can be performed. Using switch (true) doesn't make much sense.

Feel free to try out a working example here

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

How can I get an object returned from a Mongoose find method in NodeJS?

I am currently working on developing a node.js API with Mongoose, However, for a specific task, I need to retrieve the object as a variable from my find operation. This is what I have so far: exports.get_info = function(_id) { Session.findById(_id, f ...

What mechanism does the useState() function utilize in React to fetch the appropriate state object and function for a functional component when employing the state hook?

Currently focusing on deepening my understanding of the useState hook in react. I have a question regarding how useState retrieves the state object and modifier function specific to each functional component when it is called. What I'm wondering is w ...

JavaScript array as a reliable data storage solution

This is my unique jsp code where I am attempting to push certain data into a JavaScript array. <% int proListSize = proList.size(); ProfileDAO proDAO = null; for(int i = 0, j=1; i < proListSize; i++){ proDAO = ( ...

The property "props" is not recognized within the context of type PropType

Within my component, I am receiving a prop ("author") from a parent component. Although I have defined the prop type as "AuthorProps", I am getting an error stating Property 'author' does not exist on type 'AuthorProps', even though the ...

My backend axios post request is not returning any data to my external API. What could be the issue?

I've encountered an issue where I'm attempting to transmit data from my client-side using an ajax call to my backend axios post request, which is responsible for posting data to an external API URL. Despite receiving a 200 status code, none of th ...

Is there a way to incorporate an "else" condition in a TypeScript implementation?

I am trying to add a condition for when there are no references, I want to display the message no data is available. Currently, I am working with ReactJS and TypeScript. How can I implement this check? <div className="overview-text"> < ...

What is the best method for utilizing the jQuery Selector in this particular web application?

I have been attempting to figure out how to select a delete icon within my personal web application. delectIcon HTML <main> <div class="container"> <div class="tabs"> <a href=""><p><span class="act ...

Retrieve data using the designated key and convert it into JSON format

If I have the following JSON array: [ {"data": [ {"W":1,"A1":"123"}, {"W":1,"A1":"456"}, {"W":2,"A1":"4578"}, {"W":2,"A1":"2423"}, {"W":2,"A1":"2432"}, {"W":2,"A1":"24324" ...

Utilizing AJAX in Django applications

I'm currently working on integrating a basic AJAX function with Django, but I seem to be facing some issues. The request.is_ajax() function is returning False, and using event.preventDefault() doesn't prevent the form from getting submitted. Her ...

I have attempted numerous methods, but the TypeScript object remains potentially undefined

My current code involves using canvas to capture the cropped image. Below is the function that handles this process: export const getCroppedImg = ( image: HTMLImageElement, crop: Crop, fileName: string ): Promise<Blob> => { let canvas: HTM ...

Passing a variable from the server to the client function in Meteor with a delay

When I invoke a server function from the client side, it executes a UNIX command and retrieves the output on the server. However, I face an issue where the result is immediately returned as undefined by Meteor.call because the exec command takes some time ...

Combining the values of a particular key with duplicate objects into a single object within an array of JSON objects using Angular and Typescript

I'm currently facing a challenge in my Angular project where I have an array of JSON objects. These objects are very similar, differing only in one key-value pair. My goal is to combine these similar objects into one while appending the varying values ...

Can I receive a PHP echo/response in Ajax without using the post method in Ajax?

Is it feasible to use Ajax for posting a form containing text and images through an HTML form, and receiving the response back via Ajax? Steps 1.) Include the form in HTML with a submit button. 2.) Submit the form to PHP, where it will process and upload ...

Tips for creating AngularJS nested transcludes

I'm currently delving into the world of angular directives/transclusion to manage the creation of custom panels within my application. Unfortunately, I seem to have hit a roadblock as the transcluded content is not displaying in the HTML. Below is th ...

Leveraging ng-repeat within ng-view

I am facing an issue with using ng-repeat inside ng-view as the data is not being displayed. I have come across suggestions on forums to use a factory, but I am hesitant to utilize a service because my $scope data relies on $routeParams for querying. var ...

auto-scrolling webpage as elements come into view

Here is some jQuery code I have: $(".col-md-12").hide(); $(".button-div").hide(); $(".featurette-divider").hide(); $(".footer").hide(); $(".first").fadeIn(1000); $(".second").delay(900).fadeIn(1000); $(".third").delay(1800).fadeIn(1000); $(".fourth").dela ...

Choosing Nested TypeScript Type Generics within an Array

I need help with extracting a specific subset of data from a GraphQL query response. type Maybe<T> = T | null ... export type DealFragmentFragment = { __typename: "Deal" } & Pick< Deal, "id" | "registeringStateEnum" | "status" | "offerS ...

Keep an ear out for socket.io within an Angular application

I am trying to connect socket.io with my angular application. I have come across some examples of creating a service that can be accessed by the controller, and I understand that part. However, I am looking for a solution where all controllers can respond ...

Using Angular routing without relying on a web server to load templates

Can templates be loaded in Angular without a web server? I came across an example here: https://groups.google.com/forum/#!topic/angular/LXzaAWqWEus but it seems to only print the template paths instead of their content. Is there a functioning example of t ...

transferring information from PHP to JavaScript through the use of JSON encoding

I am currently in the process of developing a Google maps page that utilizes latitude and longitude data coordinates to generate a heat map displaying the distribution of foxes within a specific area. At present, my application functions properly when the ...