readWkbHeader(expectedTypeId) {
    const byteOrder = this.readUint8();
    const isLittleEndian = byteOrder > 0;

    const wkbType = this.readUint32(isLittleEndian);
    const wkbTypeThousandth = Math.floor((wkbType & 0x0fffffff) / 1000);
    const hasZ =
      Boolean(wkbType & 0x80000000) ||
      wkbTypeThousandth === 1 ||
      wkbTypeThousandth === 3;
    const hasM =
      Boolean(wkbType & 0x40000000) ||
      wkbTypeThousandth === 2 ||
      wkbTypeThousandth === 3;
    const hasSRID = Boolean(wkbType & 0x20000000);
    const typeId = (wkbType & 0x0fffffff) % 1000; // Assume 1000 is an upper limit for type ID
    const layout = /** @type {import("../geom/Geometry.js").GeometryLayout} */ (
      ['XY', hasZ ? 'Z' : '', hasM ? 'M' : ''].join('')
    );

    const srid = hasSRID ? this.readUint32(isLittleEndian) : null;

    if (expectedTypeId !== undefined && expectedTypeId !== typeId) {
      throw new Error('Unexpected WKB geometry type ' + typeId);
    }

    if (this.initialized_) {
      // sanity checks
      if (this.isLittleEndian_ !== isLittleEndian) {
        throw new Error('Inconsistent endian');
      }
      if (this.layout_ !== layout) {
        throw new Error('Inconsistent geometry layout');
      }
      if (srid && this.srid_ !== srid) {
        throw new Error('Inconsistent coordinate system (SRID)');
      }
    } else {
      this.isLittleEndian_ = isLittleEndian;
      this.hasZ_ = hasZ;
      this.hasM_ = hasM;
      this.layout_ = layout;
      this.srid_ = srid;
      this.initialized_ = true;
    }

    return typeId;
  }
@param {number} [expectedTypeId] Expected WKB Type ID
@return {number} WKB Type ID