# 类型推导

> 

Dujie 支持局部、可解释的类型推导。

## 基本规则

- `let x = expr` 只在 `expr` 类型唯一时允许推导
- 推导不会跨很远的上下文做复杂反推
- 函数返回类型必须显式写出

## 基础字面量

```dj
let age = 25;      // int
let pi = 3.14;     // float
let ok = true;     // bool
let name = "dujie"; // string
let ch = 'd';      // rune
```

## 容器字面量

```dj
let numbers = [1, 2, 3];           // list<int>
let names = ["a", "b"];            // list<string>
let scores = { "a": 1, "b": 2 };   // map<string, int>
```

要求：

- `list` 元素类型必须一致
- `map` 的 key 类型必须一致，value 类型必须一致
- 不做 `int` / `float` 混合推导

## `opt<T>` 推导

```dj
let a = some("x");   // opt<string>
let b = some(1);     // opt<int>
```

`none` 不能独立推出类型：

```dj
let x = none         // 不合法
let y: opt<string> = none
```

## 无法独立推导的情况

这些表达式单独使用时必须依赖上下文或显式类型：

```dj
let a = []
let b = {}
let c = none
```

例如：

```dj
let a: list<int> = []
let b: map<string, int> = {}
let c: opt<string> = none
```

## `if` 表达式

`if` 两个分支的结果类型必须一致：

```dj
let label = if ok {
    "yes"
} else {
    "no"
}
```

这类不合法：

```dj
let x = if ok {
    1
} else {
    "no"
}
```

## 不做的推导

当前不做这些事情：

- `int` / `float` 混合运算自动提升
- 因为空字面量推不出类型时自动落成 `any`
- 从赋值目标反推复杂泛型函数实参
