function property(string $name, $value = null): self {
    $isArray = is_array($this->target) || $this->target instanceof \ArrayAccess;
    if (!$isArray && !is_object($this->target)) throw new \BadMethodCallException('The target is not an array nor an object.');

    $hasProperty = $isArray ? array_key_exists($name, $this->target) : property_exists($this->target, $name);
    $hasPropertyConstraint = $isArray ? arrayHasKey($name) : objectHasAttribute($name);
    $property = $isArray ? ($this->target[$name] ?? null) : ($this->target->$name ?? null);

    if (!$hasProperty || $value === null) $this->expect($this->target, $hasPropertyConstraint);
    else {
      assertThat($this->target, $hasPropertyConstraint);
      $this->expect($property, equalTo($value));
    }

    $this->target = $property;
    return $this;
  }