handleTileJSONResponse(tileJSON) {
    const epsg4326Projection = getProjection('EPSG:4326');

    const sourceProjection = this.getProjection();
    let extent;
    if (tileJSON['bounds'] !== undefined) {
      const transform = getTransformFromProjections(
        epsg4326Projection,
        sourceProjection,
      );
      extent = applyTransform(tileJSON['bounds'], transform);
    }

    const gridExtent = extentFromProjection(sourceProjection);
    const minZoom = tileJSON['minzoom'] || 0;
    const maxZoom = tileJSON['maxzoom'] || 22;
    const tileGrid = createXYZ({
      extent: gridExtent,
      maxZoom: maxZoom,
      minZoom: minZoom,
    });
    this.tileGrid = tileGrid;

    this.template_ = tileJSON['template'];

    const grids = tileJSON['grids'];
    if (!grids) {
      this.setState('error');
      return;
    }

    this.tileUrlFunction_ = createFromTemplates(grids, tileGrid);

    if (tileJSON['attribution']) {
      const attributionExtent = extent !== undefined ? extent : gridExtent;
      this.setAttributions(function (frameState) {
        if (intersects(attributionExtent, frameState.extent)) {
          return [tileJSON['attribution']];
        }
        return null;
      });
    }

    this.setState('ready');
  }
TODO: very similar to ol/source/TileJSON#handleTileJSONResponse
@protected
@param {import("./TileJSON.js").Config} tileJSON Tile JSON.