Repository: wevm/viem (TypeScript)

Issue:
bug: args typing regression
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Package Version

2.0.3

### Current Behavior

since `2.0.0`, `args` property type is inferred to `unknown[]` instead of the correct type.

### Expected Behavior

`args` should be inferred to `[number]` in provided example.

It works properly in version `1.21.4`

### Steps To Reproduce

_No response_

### Link to Minimal Reproducible Example (StackBlitz, CodeSandbox, GitHub repo etc.)

https://stackblitz.com/edit/viem-getting-started-nnlghk?file=index.ts

### Anything else?

_No response_


Discussion: Will take a look. In addition, your minimal reproduction ABI doesn't have any payable or nonpayable functions.
@tmm good point. This is just an error in the example, it doesn’t infer types properly with write function either.



Fix (patch):
diff --git a/.changeset/serious-drinks-hammer.md b/.changeset/serious-drinks-hammer.md
new file mode 100644
index 0000000000..e0eb71edc8
--- /dev/null
+++ b/.changeset/serious-drinks-hammer.md
@@ -0,0 +1,5 @@
+---
+"viem": patch
+---
+
+Fixed `writeContract` `args` type inference.
diff --git a/src/actions/wallet/writeContract.ts b/src/actions/wallet/writeContract.ts
index be5828ac3c..d4686a478f 100644
--- a/src/actions/wallet/writeContract.ts
+++ b/src/actions/wallet/writeContract.ts
@@ -136,7 +136,11 @@ export async function writeContract<
   account extends Account | undefined,
   const abi extends Abi | readonly unknown[],
   functionName extends ContractFunctionName<abi, 'nonpayable' | 'payable'>,
-  args extends ContractFunctionArgs<abi, 'pure' | 'view', functionName>,
+  args extends ContractFunctionArgs<
+    abi,
+    'nonpayable' | 'payable',
+    functionName
+  >,
   chainOverride extends Chain | undefined,
 >(
   client: Client<Transport, chain, account>,
diff --git a/src/types/contract.ts b/src/types/contract.ts
index 6bcdc21f45..74cf152f7e 100644
--- a/src/types/contract.ts
+++ b/src/types/contract.ts
@@ -168,21 +168,22 @@ export type ExtractAbiFunctionForArgs<
   ? IsUnion<abiFunction> extends true // narrow overloads using `args` by converting to tuple and filtering out overloads that don't match
     ? UnionToTuple<abiFunction> extends infer abiFunctions extends
         readonly AbiFunction[]
-      ? {
-          [k in keyof abiFunctions]: (
-            readonly [] extends args
-              ? readonly [] // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided)
-              : args
-          ) extends AbiParametersToPrimitiveTypes<
-            abiFunctions[k]['inputs'],
-            'inputs'
-          >
-            ? abiFunctions[k]
-            : never
-        }[number] // convert back to union (removes `never` tuple entries: `['foo', never, 'bar'][number]` => `'foo' | 'bar'`)
+      ? // convert back to union (removes `never` tuple entries)
+        { [k in keyof abiFunctions]: CheckArgs<abiFunctions[k], args> }[number]
       : never
     : abiFunction
   : never
+type CheckArgs<
+  abiFunction extends AbiFunction,
+  args,
+  ///
+  targetArgs extends AbiParametersToPrimitiveTypes<
+    abiFunction['inputs'],
+    'inputs'
+  > = AbiParametersToPrimitiveTypes<abiFunction['inputs'], 'inputs'>,
+> = (readonly [] extends args ? readonly [] : args) extends targetArgs // fallback to `readonly []` if `args` has no value (e.g. `args` property not provided)
+  ? abiFunction
+  : never
 
 export type ContractFunctionParameters<
   abi extends Abi | readonly unknown[] = Abi,