protected function validateType($field, $val, $type, $required = true)
    {
        if ($val !== null) {
            if ($type === 'string') {
                $result = is_string($val);
            } elseif ($type === 'non-numeric string') {
                $result = is_string($val) && !is_numeric($val);
            } elseif ($type === 'int' || $type === 'integer') {
                $result = is_int($val);
            } elseif ($type === "numeric") {
                $result = is_numeric($val);
            } elseif ($type === 'non-string numeric') {
                $result = !is_string($val) && is_numeric($val);
            } elseif ($type === 'string or int') {
                $result = is_string($val) || is_int($val);
            } elseif ($type === 'boolean' || $type === 'bool') {
                $result = is_bool($val);
            } elseif ($type === 'datetime') {
                $result = ($val instanceof \DateTime);
            } elseif ($type === 'email') {
                $result = is_string($val) && preg_match($this->getKnownFormat("email"), $val);
            } elseif ($type === 'uri') {
                $result = is_string($val) && preg_match($this->getKnownFormat("uri"), $val);
            } elseif ($type === 'url') {
                $result = is_string($val) && preg_match($this->getKnownFormat("url"), $val) && $val !== "";
            } else {
                throw new \RuntimeException("Programmer: Don't know how to validate for type `$type`!");
            }
        } else {
            $result = !$required;
        }

        if ($result) {
            $this->clearError($field, 'validType');
            return true;
        } else {
            $this->setError($field, 'validType', [
                "title" => "Invalid Value for Field `$field`",
                "detail" => "Field `$field` must be a(n) $type value."
            ]);
            return false;
        }
    }