TypeScript
viem is designed to be as type-safe as possible! Things to keep in mind:
- Types currently require using TypeScript v5.0.4 or greater.
- Changes to types in this repository are considered non-breaking and are usually released as patch semver changes (otherwise every type enhancement would be a major version!).
- It is highly recommended that you lock your
viempackage version to a specific patch release and upgrade with the expectation that types may be fixed or upgraded between any release. - The non-type-related public API of
viemstill follows semver very strictly.
To ensure everything works correctly, make sure that your tsconfig.json has strict mode set to true:
{
"compilerOptions": {
"strict": true
}
}Type Inference
viem can infer types based on ABI and EIP-712 Typed Data definitions (powered by ABIType), giving you full end-to-end type-safety from your contracts to your frontend and incredible developer experience (e.g. autocomplete ABI function names and catch misspellings, strongly-typed ABI function arguments, etc.).
For this to work, you must either add const assertions to specific configuration parameters (more info on those below) or define them inline. For example, readContract's abi configuration parameter:
const abi = [{
type: 'function',
name: 'balanceOf',
stateMutability: 'view',
inputs: [{ type: 'address' }],
outputs: [{ type: 'uint256' }],
}] as const
↑ const assertion const result = client.readContract({
address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
abi,
functionName: 'balanceOf',
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC']
}) ↓ defined inlineconst result = client.readContract({ address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
abi: [{
type: 'function',
name: 'balanceOf',
stateMutability: 'view',
inputs: [{ type: 'address' }],
outputs: [{ type: 'uint256' }],
}],
functionName: 'balanceOf',
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC']
})If type inference isn't working, it's likely you forgot to add a const assertion or define the configuration parameter inline.
Contract ABIs
The following actions and utilities support type inference when you add a const assertion to abi or define abi inline:
Actions
createEventFilterwatchEventcreateContractEventFilterdeployContractestimateContractGasmulticallreadContractsimulateContractwriteContractwatchContractEvent
Utilities
decodeEventLogdecodeFunctionResultencodeDeployDataencodeErrorResultencodeEventTopicsencodeFunctionDataencodeFunctionResultgetAbiItem
For example, readContract:
const const result: bigintresult = await client.readContract({
address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
abi: erc20Abi,
functionName: "symbol" | "name" | "balanceOf" | "allowance" | "decimals" | "totalSupply"functionName: 'balanceOf',
// ↑ Notice how "transfer" is not included since it is not a "read" function
args: readonly [`0x${string}`]args: ['0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c'],
})EIP-712 Typed Data
Adding a const assertion to types or defining types inline adds type inference to signTypedData's value configuration parameter:
const result = client.signTypedData({
domain: {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
types: {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' },
],
},
primaryType: 'Mail',
message: {
from: {
name: string;
wallet: `0x${string}`;
};
to: {
name: string;
wallet: `0x${string}`;
};
contents: string;
}message: {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
contents: 'Hello, Bob!',
},
})Other
The following utilities support type inference when you use const assertions or define arguments inline:
decodeAbiParametersencodeAbiParametersencodePackedparseAbiparseAbiItemparseAbiParameterparseAbiParameters
Configuring Internal Types
For advanced use-cases, you may want to configure viem's internal types. Most of viem's types relating to ABIs and EIP-712 Typed Data are powered by ABIType. See ABIType's documentation for more info on how to configure types.
window Polyfill
By importing the viem/window Polyfill, the global window.ethereum will typed as an EIP1193Provider (including a fully-typed request function & typed events).
import 'viem/window';
const hash = await window.ethereum.request({
method: 'eeth_blobBaseFeeeth_blockNumbereth_chainIdeth_coinbaseeth_gasPriceeth_maxPriorityFeePerGaseth_newBlockFiltereth_newPendingTransactionFiltereth_protocolVersioneth_accountseth_requestAccountseth_syncingeth_supportedEntryPoints
})
const hash = await window.ethereum.request({
method: 'eth_getTransactionByHash',
params: [hash: `0x${string}`]params: [
})