Búsqueda de sitios web

javascript - La propiedad 'xxx' no existe en el tipo 'Readonly<{}>'


Estoy intentando escribir pruebas para un componente de React en Typescript. App.tsx:

import * as React from 'react';
import { Button } from 'react-bootstrap';

interface Igift {
  id: number;
}
interface IAppState {
  gifts: Igift[];
}
class App extends React.Component<{}, IAppState> {
  public state = {
    gifts: []
  };

  public addGift = () => {
    const { gifts } = this.state;
    const ids = this.state.gifts.map(ourGift => ourGift.id);

    const maxId = ids.length > 0 ? Math.max(...ids) : 0;

    gifts.push({ id: maxId + 1 });

    this.setState({ gifts });
  };

  public render() {
    return (
      <div>
        <h2>Gift Giver</h2>
        <Button className="btn-add" onClick={this.addGift}>
          Add Gift
        </Button>
      </div>
    );
  }
}

export default App;

y una prueba para ese componente. App.test.tsx:

import { shallow } from 'enzyme';
import * as React from 'react';

import App from './App';

const app = shallow(<App />);

describe('App', () => {
  it('renders correctly', () => {
    expect(app).toMatchSnapshot();
  });

  it('initializes the `state` with an empty list of gifts', () => {
    expect(app.state().gifts).toEqual([]);
  });

  it('adds a new gift to `state` when clicking the `add gift` button', () => {
    app.find('.btn-add').simulate('click');

    expect(app.state().gifts).toEqual([{ id: 1 }]);
  });
});

Estoy recibiendo el siguiente error:

(14,24): Property 'gifts' does not exist on type 'Readonly<{}>'.

En App.test.tsx no parece que pueda encontrar ningún detalle al respecto. La aplicación se inicializa con create-react-app con la versión ts de los scripts. Las pruebas pasan, pero cuando intento iniciar la aplicación, lanza ese error. ¿Qué se necesita hacer?

Respuesta #1

Debido a que <App/> tiene el tipo genérico JSX.Element, no contiene suficiente información para inferir el tipo de estado en el resultado de shallow (lo mismo aplica para los tipos de props y del componente). Puedes solucionarlo exportando IAppState desde App.tsx y parametrizando shallow con los tipos de componente, props y estado:

import App, {IAppState} from './App';
..
const app = shallow<App, {}, IAppState>(<App />); // {} is props type
..

Esto también debería tipar correctamente app.instance() y app.setProps(). Alternativamente, podrías optar por probar solo en JavaScript puro, ya que no estoy seguro de que hacerlo en TypeScript valga el esfuerzo adicional.

Artículos relacionados