# How it's possible that

**URL:** <https://forum.crystal-lang.org/t/how-its-possible-that/1677>\
**Category:** Offtopic\
**Created:** [February 5, 2020, 3:58pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677 "2020-02-05T15:58:43Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![valenciaj](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/valenciaj/32/1446_2.png) [@valenciaj](https://forum.crystal-lang.org/u/valenciaj)\
**Post date:** [February 5, 2020, 3:58pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/1 "2020-02-05T15:58:43Z")

</div>

I have a class constructor with variable called @headers typed as a Hash(String, Array(String) | String), but I got this error when I call it.

`Error: instance variable '@headers' of HTTPHeaders must be Hash(String, Array(String) | String), not Hash(String, Array(String))`

Why can’t compiler infer my variable with constructor type?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [February 5, 2020, 4:02pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/2 "2020-02-05T16:02:30Z")

</div>

Unrelated to your issue, this type already exists. Probably would be easier to just use [https://crystal-lang.org/api/master/HTTP/Headers.html](https://crystal-lang.org/api/master/HTTP/Headers.html).

The issue you’re seeing is that `Hash(String, Array(String) | String)` is NOT the same type as `Hash(String, Array(String))`. You would need to cast your hash to the proper type. For example.

```auto
HTTPHeaders.new({"foo" => ["one","two"]} of String => Array(String) | String)

```

The reasoning is since the ivar should allow both `Array(String)` and `String` values, while the hash you’re trying to pass in would not allow plain `String` values. using `of ...` tells it that it should also allow `String` values.

---

<div class="post-metadata">

**Author:** ![valenciaj](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/valenciaj/32/1446_2.png) [@valenciaj](https://forum.crystal-lang.org/u/valenciaj)\
**Post date:** [February 5, 2020, 4:06pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/3 "2020-02-05T16:06:44Z")

</div>

But why?

My var it’s more restrictive than the constructor type.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [February 5, 2020, 4:15pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/4 "2020-02-05T16:15:03Z")

</div>

> [@valenciaj](#):
>
> My var it’s more restrictive than the constructor type.

That’s the issue. The types must exactly match.

If you could assign a hash of type `Hash(String, Array(String))` to a variable restricted to `Hash(String, Array(String) | String)`, what would happen if you call `#<<(String)` on that variable? The variable is restricted to a hash type with `Array(String) | String` values, so you should be able to add `String`. The actual object needs to be able to handle such a call, hence the requirement to for exact type matching, no invariants.  
An easy way to transform the hash is `hash.transform_values { |value| value.as(Array(String) | String) }`

---

<div class="post-metadata">

**Author:** ![valenciaj](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/valenciaj/32/1446_2.png) [@valenciaj](https://forum.crystal-lang.org/u/valenciaj)\
**Post date:** [February 5, 2020, 4:17pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/5 "2020-02-05T16:17:44Z")

</div>

I’m too lazy to write additionals `of String => Array(String)|String` 😉

---

<div class="post-metadata">

**Author:** ![ComputerMage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/computermage/32/719_2.png) [@ComputerMage](https://forum.crystal-lang.org/u/ComputerMage)\
**Post date:** [February 5, 2020, 4:18pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/6 "2020-02-05T16:18:49Z")

</div>

You can alias that:  
alias Headers = String =\> Array(String)|String

---

<div class="post-metadata">

**Author:** ![valenciaj](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/valenciaj/32/1446_2.png) [@valenciaj](https://forum.crystal-lang.org/u/valenciaj)\
**Post date:** [February 5, 2020, 4:26pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/7 "2020-02-05T16:26:32Z")

</div>

Será `alias Headers = {} of String => Array(String)|String`

---

<div class="post-metadata">

**Author:** ![ComputerMage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/computermage/32/719_2.png) [@ComputerMage](https://forum.crystal-lang.org/u/ComputerMage)\
**Post date:** [February 5, 2020, 4:31pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/8 "2020-02-05T16:31:07Z")

</div>

> [@valenciaj](#):
>
> Será

Yeah, I did typed from the top of my head so pardon me for mistakes. But main idea is correct ;)

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [February 5, 2020, 4:41pm UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/9 "2020-02-05T16:41:52Z")

</div>

I would probably just use the stdlib’s `HTTP::Headers` type versus trying to roll your own. Then you could type stuff to `HTTP::Headers` and use it via `HTTP::Headers{"content-type" => "text/css"}`.

---

<div class="post-metadata">

**Author:** ![valenciaj](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/valenciaj/32/1446_2.png) [@valenciaj](https://forum.crystal-lang.org/u/valenciaj)\
**Post date:** [February 6, 2020, 9:00am UTC](https://forum.crystal-lang.org/t/how-its-possible-that/1677/10 "2020-02-06T09:00:55Z")

</div>

`HTTPHeaders` it’s hyperbole. It’s a propietary protocol, but HTTP like.
