# 类型
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 类型将遵循以下层次结构 🦄
虚线元素未公开和/或不清楚。`(...)` 占位符表示具体子类型,例如特定元素类型的数组、具有特定字段类型的结构体,以及可能的超类型或具有特定参数和返回值类型的函数。有关详细信息,请参阅 Wasm GC 的子类型规则 (在新窗口中打开).
# 可比性
比较两个不同类型的值可以在没有显式转换的情况下执行,只要遵循上面可分配性中概述的相同规则
- 如果比较是绝对的(`==` 或 `===`,`!=` 或 `!==`)
- 如果比较是相对的(`>`,`<`,`>=`,`<=`)并且 **两种类型具有相同的符号**
因为 WebAssembly 针对有符号和无符号比较有不同的操作。比较使用较大的类型并返回 `bool`。
请注意,`==` 和 `===` 以及 `!=` 和 `!==` 在 AssemblyScript 中是相同的,因为在它的严格类型规则下,比较两个不同类型的值无论如何都是无效的。
# 位移
位移(`<<`,`>>`)的结果是左侧类型,右侧类型隐式转换为左侧类型,如果左侧类型是有符号的,则执行算术移位,如果左侧类型是无符号的,则执行逻辑移位。
无符号右移(`>>>`)的结果是左侧类型(符号性保持不变),右侧类型隐式转换为左侧类型,但始终执行逻辑移位。
请注意,只有移位的 `log2(sizeof<T>())` 最低有效位影响结果
类型 | 有效位 | 示例 |
---|---|---|
i8 / u8 | 3 | x << y ≡ x << (y & 7) |
i16 / u16 | 4 | x << y ≡ x << (y & 15) |
i32 / u32 | 5 | x << y ≡ x << (y & 31) |
i64 / u64 | 6 | x << y ≡ x << (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