# 类型

AssemblyScript 继承了 WebAssembly 更具体的整数、浮点数和引用类型

AssemblyScript 类型 WebAssembly 类型 TypeScript 类型 描述
整数类型
i32 i32 number 32 位有符号整数。
u32 i32 number 32 位无符号整数。
i64 i64 bigint 64 位有符号整数。
u64 i64 bigint 64 位无符号整数。
isize i32 或 i64 number 或 bigint 在 WASM32 中为 32 位有符号整数。
在 WASM64 🦄 中为 64 位有符号整数。
usize i32 或 i64 number 或 bigint 在 WASM32 中为 32 位无符号整数。
在 WASM64 🦄 中为 64 位无符号整数。
浮点类型
f32 f32 number 32 位浮点数。
f64 f64 number 64 位浮点数。
小整数类型
i8 i32 number 8 位有符号整数。
u8 i32 number 8 位无符号整数。
i16 i32 number 16 位有符号整数。
u16 i32 number 16 位无符号整数。
bool i32 boolean 1 位无符号整数。
向量类型
v128 v128 - 128 位向量。
引用 / GC 类型
ref_extern (ref extern) Object 外部引用。
ref_func (ref func) Function 函数引用。
ref_any (ref any) Object 内部引用。🦄
ref_eq (ref eq) Object 可比较引用。🦄
ref_struct (ref struct) Object 数据引用。🦄
ref_array (ref array) Array 数组引用。🦄
ref_string (ref string) string 字符串引用。🦄
ref_stringview_wtf8 (ref stringview_wtf8) - WTF-8 字符串视图引用。🦄
ref_stringview_wtf16 (ref stringview_wtf16) string WTF-16 字符串视图引用。🦄
ref_stringview_iter (ref stringview_iter) - 字符串迭代器引用。🦄
特殊类型
void - void 表示没有返回值。

注意

上面的基本引用类型是不可为空的。根据规范,规范别名也可用,并指代相应的可为空类型,例如 `type externref = ref_extern | null` 映射到 Wasm 中的 `externref == (ref null extern)`。`ref_` 前缀暂时避免了命名冲突,将来可能会被删除。

就像在 TypeScript 中一样,类型在变量、函数参数或类成员名称后用 `:` 分隔,如下所示

function add(a: i32, b: i32): i32 {
  let sum: i32 = a + b; // type can be inferred, annotation can be omitted
  return sum;
}

# 类型规则

当编译器看到可能并非真正想要的隐式转换时,它会发出警告,这与 C 编译器所做的事情非常相似。

# 转换

在 AssemblyScript 中,从 TypeScript 中知道的类型断言 `<T>expression` 和 `expression as T` 成为显式类型转换,本质上告诉编译器转换是故意的。此外,除了别名之外,上面提到的每个类型名称也充当可移植的转换内置函数,可以像 `i32(expression)` 一样使用。使用可移植转换在以下情况下特别有用:希望使用 TypeScript 编译器 (参见) 编译完全相同的代码到 JavaScript,否则将需要插入 asm.js 样式的类型强制,例如 `expression | 0`。

# 推断

与 TypeScript 相比,AssemblyScript 中的类型推断有限,因为必须事先知道每个表达式的类型。这意味着变量和参数声明必须要么有它们的类型注释,要么有初始化器。如果没有类型注释,只有初始化器,AssemblyScript 将首先假设 `i32`,并且只有当值不适合(变为 `i64`)、是浮点数(变为 `f64`)或不可否认地与这些类型不同时,才会重新考虑另一种类型,例如变量的类型、函数的返回值类型或类类型。此外,函数必须用返回值类型进行注释,以帮助编译器做出正确的决定,例如在返回文字或存在多个 return 语句的情况下。

# 可空性

基本类型不可为空,但类和函数类型可以。附加 `| null` 声明一个可为空类型。

# 可分配性

将一个类型的值分配给另一个类型的目标,可以在没有显式转换的情况下执行,只要目标类型可以表示所有可能的值,而与解释/符号无关

bool i8/u8 i16/u16 i32/u32 i64/u64 f32 f64
bool
i8/u8
i16/u16
i32/u32
i64/u64
f32
f64

请注意,`isize` 和 `usize` 分别是 WASM32 中 `i32` 和 `u32` 以及 WASM64 🦄 中 `i64` 和 `u64` 的别名。

var  i8val: i8  = -128  // 0x80
var  u8val: u8  = i8val // becomes 128 (0x80)
var i16val: i16 = i8val // becomes -128 through sign-extension (0xFF80)
var u16val: u16 = i8val // becomes 65408 through masking (0xFF80)
var f32val: f32 = i8val // becomes -128.0

预计 Wasm 引用和 GC 类型将遵循以下层次结构 🦄

Diagram of anticipated reference types hierarchy.

虚线元素未公开和/或不清楚。`(...)` 占位符表示具体子类型,例如特定元素类型的数组、具有特定字段类型的结构体,以及可能的超类型或具有特定参数和返回值类型的函数。有关详细信息,请参阅 Wasm GC 的子类型规则 (在新窗口中打开).

# 可比性

比较两个不同类型的值可以在没有显式转换的情况下执行,只要遵循上面可分配性中概述的相同规则

  1. 如果比较是绝对的(`==` 或 `===`,`!=` 或 `!==`)
  2. 如果比较是相对的(`>`,`<`,`>=`,`<=`)并且 **两种类型具有相同的符号**

因为 WebAssembly 针对有符号和无符号比较有不同的操作。比较使用较大的类型并返回 `bool`。

请注意,`==` 和 `===` 以及 `!=` 和 `!==` 在 AssemblyScript 中是相同的,因为在它的严格类型规则下,比较两个不同类型的值无论如何都是无效的。

# 位移

位移(`<<`,`>>`)的结果是左侧类型,右侧类型隐式转换为左侧类型,如果左侧类型是有符号的,则执行算术移位,如果左侧类型是无符号的,则执行逻辑移位。

无符号右移(`>>>`)的结果是左侧类型(符号性保持不变),右侧类型隐式转换为左侧类型,但始终执行逻辑移位。

请注意,只有移位的 `log2(sizeof<T>())` 最低有效位影响结果

类型 有效位 示例
i8 / u8 3 x << yx << (y & 7)
i16 / u16 4 x << yx << (y & 15)
i32 / u32 5 x << yx << (y & 31)
i64 / u64 6 x << yx << (y & 63)

如果左侧类型是浮点数,则会发出错误。

# 宏类型

以下宏类型提供了对相关类型的访问,否则无法获得这些类型。

宏类型 描述
native<T> 获取 `T` 的底层原生类型,例如,如果 `T` 是一个类(在 WASM32 中),则为 `u32`。
indexof<T> 根据索引访问重载获取集合的索引类型。
valueof<T> 根据索引访问重载获取集合的值类型。
returnof<T> 获取函数类型的返回值类型。

# 范围限制

为了方便起见,各种特定于 WebAssembly 类型的范围限制作为全局常量存在。

  • const i8.MIN_VALUE: i8 = -128
    const i8.MAX_VALUE: i8 = 127
    
  • const i16.MIN_VALUE: i16 = -32768
    const i16.MAX_VALUE: i16 = 32767
    
  • const i32.MIN_VALUE: i32 = -2147483648
    const i32.MAX_VALUE: i32 = 2147483647
    
  • const i64.MIN_VALUE: i64 = -9223372036854775808
    const i64.MAX_VALUE: i64 = 9223372036854775807
    
  • const isize.MIN_VALUE: isize // WASM32: i32.MIN_VALUE, WASM64: i64.MIN_VALUE
    const isize.MAX_VALUE: isize // WASM32: i32.MAX_VALUE, WASM64: i64.MAX_VALUE
    
  • const u8.MIN_VALUE: u8 = 0
    const u8.MAX_VALUE: u8 = 255
    
  • const u16.MIN_VALUE: u16 = 0
    const u16.MAX_VALUE: u16 = 65535
    
  • const u32.MIN_VALUE: u32 = 0
    const u32.MAX_VALUE: u32 = 4294967295
    
  • const u64.MIN_VALUE: u64 = 0
    const u64.MAX_VALUE: u64 = 18446744073709551615
    
  • const usize.MIN_VALUE: usize = 0
    const usize.MAX_VALUE: usize // WASM32: u32.MAX_VALUE, WASM64: u64.MAX_VALUE
    
  • const bool.MIN_VALUE: bool = 0
    const bool.MAX_VALUE: bool = 1
    
  • const f32.MIN_VALUE: f32 = -3.40282347e+38
    const f32.MAX_VALUE: f32 = 3.40282347e+38
    const f32.MIN_NORMAL_VALUE: f32 = 1.17549435e-38
    const f32.MIN_SAFE_INTEGER: f32 = -16777215
    const f32.MAX_SAFE_INTEGER: f32 = 16777215
    const f32.EPSILON: f32 = 1.19209290e-07
    
  • const f64.MIN_VALUE: f64 = -1.7976931348623157e+308
    const f64.MAX_VALUE: f64 = 1.7976931348623157e+308
    const f64.MIN_NORMAL_VALUE: f64 = 2.2250738585072014e-308
    const f64.MIN_SAFE_INTEGER: f64 = -9007199254740991
    const f64.MAX_SAFE_INTEGER: f64 = 9007199254740991
    const f64.EPSILON: f64 = 2.2204460492503131e-16