# Type inference issue on instance variables

**URL:** https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281
**Category:** Help & Support
**Created:** [May 7, 2021, 9:42pm UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281 "2021-05-07T21:42:32Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![monomonedula](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/monomonedula/32/1271_2.png) [@monomonedula](https://forum.crystal-lang.org/u/monomonedula)
#### Post date: [May 7, 2021, 9:42pm UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/1 "2021-05-07T21:42:32Z")

</div>

Why can I define a method like that:

```crystal
def foo(bar): String
  bar.to_json
end

foo({"x" => 1, "y" => 2})

```

but that kind of type inference doesn’t work with classes:

```crystal
class Foo
  def initialize(bar)
    @bar = bar
  end

  def foo: String
    @bar.to_json
  end
end

Foo.new({"x" => 1, "y" => 2}).foo

```

and it ends up with

`Error: can't infer the type of instance variable '@bar' of Foo`

What am I missing about Crystal’s type inference and what is the workaround for this?

---

<div class="post-metadata">

### Author: ![mavu](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/mavu/32/213_2.png) [@mavu](https://forum.crystal-lang.org/u/mavu)
#### Post date: [May 7, 2021, 9:57pm UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/2 "2021-05-07T21:57:49Z")

</div>

I’m no expert here, but i’d like to have a go:

> [@monomonedula](#):
>
> ```auto
> def foo: String
> @bar.to_json
> end
> 
> ```

This defines a function that returns a string. and .to\_json returns a string.  
But, this does not put any constraints no @bar. anything that has a .to\_json could be in @bar.

Does that sound right?

---

<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: [May 7, 2021, 10:04pm UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/3 "2021-05-07T22:04:50Z")

</div>

Checkout [Type inference - Crystal](https://crystal-lang.org/reference/syntax_and_semantics/type_inference.html).

The first example is an example of duck typing. I.e. the compiler figures out all invocations of `#foo` and knows that each value passed to it responds to `.to_json`.

However the 2nd example is introducing an instance variable which needs to be typed and known ahead of time. I.e. there’s not really a way the compiler can type this, as the error says because it doesn’t comply with the inference rules.

The solution is to type your ivar. E.g.

```auto
  def initialize(@bar : Hash(String, Int32))
  end

```

---

<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: [May 7, 2021, 10:33pm UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/4 "2021-05-07T22:33:05Z")

</div>

To expand on the previous comments: Technically, the compiler could figure out that the call to `Foo.new` receives a `Hash` and thus type the instance variable accordingly.  
In fact, this used to work in earlier iterations of the language. But it was later changed, because it involved too much magic to be sane (that’s my interpretation at least; I wasn’t around at that time, though).  
Now type instance variables require a type restrictions. In many simple cases, the type can be inferred from the variable assignment (for example, when the value is a literal).

For the details behind the change, I recommend [The next step · Issue #1824 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/issues/1824)

---

<div class="post-metadata">

### Author: ![monomonedula](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/monomonedula/32/1271_2.png) [@monomonedula](https://forum.crystal-lang.org/u/monomonedula)
#### Post date: [May 8, 2021, 7:57am UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/5 "2021-05-08T07:57:37Z")

</div>

> [@Blacksmoke16](#):
>
> `Hash(String, Int32)`

OK, but what if I want to generalize it to mean any type that has `to_json` method returning a `String`?

---

<div class="post-metadata">

### Author: ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)
#### Post date: [May 8, 2021, 9:47am UTC](https://forum.crystal-lang.org/t/type-inference-issue-on-instance-variables/3281/6 "2021-05-08T09:47:50Z")

</div>

Could you show us some more code and what you are trying to achieve? Talking about these things in isolation sometimes isn’t good. There might be a better way to do what you want.
