# TypeScript \[TypeScript support for Viem]

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 `viem` package 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 `viem` still follows semver very strictly.

To ensure everything works correctly, make sure that your `tsconfig.json` has [`strict`](https://www.typescriptlang.org/tsconfig#strict) mode set to `true`:

```json [tsconfig.json]
{
  "compilerOptions": {
    "strict": true // [!code focus]
  }
}
```

## Type Inference

viem can infer types based on [ABI](https://docs.soliditylang.org/en/v0.8.24/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions (powered by [ABIType](https://abitype.dev)), 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](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4#const-assertions) to specific configuration parameters (more info on those below) or **define them inline**. For example, [`readContract`](/docs/contract/readContract)'s `abi` configuration parameter:

```ts twoslash
import { createPublicClient, http, parseAbi } from 'viem'

const client = createPublicClient({
  transport: http()
})
// ---cut---
const abi = [{ // [!code focus]
  type: 'function', // [!code focus]
  name: 'balanceOf', // [!code focus]
  stateMutability: 'view', // [!code focus]
  inputs: [{ type: 'address' }], // [!code focus]
  outputs: [{ type: 'uint256' }], // [!code focus]
}] as const // [!code focus]
// @log:       ↑ const assertion

const result = client.readContract({
  address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
  abi, 
  functionName: 'balanceOf',
  args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC']
})
```

```ts twoslash
import { createPublicClient, http, parseAbi } from 'viem'

const client = createPublicClient({
  transport: http()
})
// ---cut---
// @log:   ↓ defined inline
const result = client.readContract({
  address: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
  abi: [{ // [!code focus]
    type: 'function', // [!code focus]
    name: 'balanceOf', // [!code focus]
    stateMutability: 'view', // [!code focus]
    inputs: [{ type: 'address' }], // [!code focus]
    outputs: [{ type: 'uint256' }], // [!code focus]
  }], // [!code focus]
  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.

:::tip
Unfortunately [TypeScript doesn't support importing JSON as const](https://github.com/microsoft/TypeScript/issues/32063). Check out [`@wagmi/cli`](https://wagmi.sh/cli) to help with this! It can automatically fetch ABIs from Etherscan, resolve ABIs from your Foundry/Hardhat projects, and much more.
:::

### Contract ABIs

The following actions and utilities support type inference when you add a const assertion to `abi` or define `abi` inline:

#### Actions

* [`createEventFilter`](/docs/actions/public/createEventFilter)
* [`watchEvent`](/docs/actions/public/watchEvent)
* [`createContractEventFilter`](/docs/contract/createContractEventFilter)
* [`deployContract`](/docs/contract/deployContract)
* [`estimateContractGas`](/docs/contract/estimateContractGas)
* [`multicall`](/docs/contract/multicall)
* [`readContract`](/docs/contract/readContract)
* [`simulateContract`](/docs/contract/simulateContract)
* [`writeContract`](/docs/contract/writeContract)
* [`watchContractEvent`](/docs/contract/watchContractEvent)

#### Utilities

* [`decodeEventLog` ](/docs/contract/decodeEventLog)
* [`decodeFunctionResult` ](/docs/contract/decodeFunctionResult)
* [`encodeDeployData` ](/docs/contract/encodeDeployData)
* [`encodeErrorResult` ](/docs/contract/encodeErrorResult)
* [`encodeEventTopics` ](/docs/contract/encodeEventTopics)
* [`encodeFunctionData` ](/docs/contract/encodeFunctionData)
* [`encodeFunctionResult` ](/docs/contract/encodeFunctionResult)
* [`getAbiItem` ](/docs/abi/getAbiItem)

For example, `readContract`:

```ts twoslash
// @noErrors
import { createPublicClient, http, erc20Abi, parseAbi } from 'viem'

const client = createPublicClient({
  transport: http()
})
// ---cut---
const result = await client.readContract({
  //  ^?


  address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
  abi: erc20Abi,
  functionName: 'balanceOf',
  //         ^?
  
  

  // ↑ Notice how "transfer" is not included since it is not a "read" function

  args: ['0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c'],
  // ^?
})
```

### EIP-712 Typed Data

Adding a const assertion to `types` or defining `types` inline adds type inference to [`signTypedData`](/docs/actions/wallet/signTypedData)'s `value` configuration parameter:

```ts twoslash
import { createWalletClient, http, erc20Abi, parseAbi } from 'viem'

const client = createWalletClient({
  account: '0x',
  transport: http()
})
// ---cut---
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: '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:

* [`decodeAbiParameters` ](/docs/abi/decodeAbiParameters)
* [`encodeAbiParameters` ](/docs/abi/encodeAbiParameters)
* [`encodePacked` ](/docs/abi/encodePacked)
* [`parseAbi` ](/docs/abi/parseAbi)
* [`parseAbiItem` ](/docs/abi/parseAbiItem)
* [`parseAbiParameter` ](/docs/abi/parseAbiParameter)
* [`parseAbiParameters` ](/docs/abi/parseAbiParameters)

## 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](https://abitype.dev). See ABIType's [documentation](https://abitype.dev/config) 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`](https://github.com/wagmi-dev/viem/blob/4bdbf15be0d61b52a195e11c97201e707fb616cc/src/types/eip1193.ts#L24-L26) (including a fully-typed `request` function & typed events).

```ts twoslash
// @noErrors
import 'viem/window';

const hash = await window.ethereum.request({
  method: 'e 
//          ^|
})








const hash = await window.ethereum.request({
  method: 'eth_getTransactionByHash',
  params: [
//     ^?
})
```
