Tact蓝图数组使用、Map长度获取及TS中Map调用技术咨询
关于Tact与TS中Map、数组使用的问题解答
一、TS代码中使用Tact定义的Map类型
你在Tact里定义的map<Int as uint16, Address>和map<Int as uint16, Int>,在TS中对应普通对象(或用Record<number, Address>/Record<number, bigint>更严谨)。构造Withdraw消息时,直接传入键值对形式的对象即可:
// 导入自动生成的Tact消息类型 import { Withdraw } from './generated/your-contract-code'; // 构造Map数据 const addressesMap: Record<number, Address> = { 0: Address.parse('EQ...'), 1: Address.parse('EQ...') }; const amountsMap: Record<number, bigint> = { 0: 1000000n, 1: 2000000n }; // 创建Withdraw消息 const withdrawMsg = Withdraw.create({ address: addressesMap, amount: amountsMap, length: 2 });
Tact的TS绑定会自动将对象序列化为合约期望的Map格式。
二、Tact蓝图中使用数组
Tact支持数组类型,仅在合约存储场景更推荐用Map(数组扩容、修改的gas成本更高),其他场景可直接使用:
1. 消息中定义数组
message Withdraw { addresses: Array<Address>; amounts: Array<Int>; }
2. 函数参数/局部变量中使用数组
fun withdrawBatch(recipients: Array<Address>, amounts: Array<Int>) { require(recipients.size() == amounts.size(), "MISMATCHED_LENGTHS"); for (let i = 0; i < recipients.size(); i++) { send(SendParameters{ to: recipients[i], value: amounts[i], mode: SendMode.PAY_GAS_SEPARATELY, body: null }); } }
3. 合约存储中使用数组(不推荐,适合固定长度场景)
contract MyContract { storedAddresses: Array<Address> = []; fun addAddress(addr: Address) { storedAddresses.push(addr); } }
三、获取Tact中Map的长度
Tact的Map没有直接的size()方法,常用两种处理方式:
- 手动维护长度变量:像你在Withdraw消息中定义的
length字段一样,修改Map时同步更新该变量:
contract MyContract { balances: map<Address, Int> = {}; balanceCount: Int as uint16 = 0; fun addBalance(addr: Address, amount: Int) { if (!balances.contains(addr)) { balanceCount += 1; } balances.set(addr, amount); } fun getBalanceCount(): Int as uint16 { return balanceCount; } }
- 遍历Map统计数量:适合偶尔统计的场景,但gas成本较高,不适合频繁调用:
fun getMapLength(m: map<Int, Address>): Int { let count = 0; for (let (k, v) in m) { count += 1; } return count; }
内容的提问来源于stack exchange,提问作者이상진
相关产品推荐
相关产品推荐

