Skip to content

Commit c0c09a6

Browse files
nikicatclaudejxom
authored
fix: accept readonly arrays in LogTopic type (#4455)
* fix: accept readonly arrays in LogTopic type LogTopic now includes `readonly Hex[]` so that `as const` and readonly arrays are assignable to topic filters without type errors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: add changeset Amp-Thread-ID: https://ampcode.com/threads/T-019dad44-c9b7-73fd-9c97-2ffe6794479e --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: jxom <7336481+jxom@users.noreply.github.com>
1 parent 870f9ce commit c0c09a6

4 files changed

Lines changed: 29 additions & 24 deletions

File tree

.changeset/readonly-log-topic.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Fixed `LogTopic` type to accept readonly arrays.

src/types/contract.test-d.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,10 @@ test('GetEventArgs', () => {
215215
'Transfer'
216216
>
217217
expectTypeOf<Result['from']>().toEqualTypeOf<
218-
`0x${string}` | `0x${string}`[] | null | undefined
218+
`0x${string}` | readonly `0x${string}`[] | null | undefined
219219
>()
220220
expectTypeOf<Result['to']>().toEqualTypeOf<
221-
`0x${string}` | `0x${string}`[] | null | undefined
221+
`0x${string}` | readonly `0x${string}`[] | null | undefined
222222
>()
223223
})
224224

@@ -260,7 +260,7 @@ test('GetValue', () => {
260260

261261
test('LogTopicType', () => {
262262
expectTypeOf<LogTopicType<string, Hex>>().toEqualTypeOf<string>()
263-
expectTypeOf<LogTopicType<string, Hex[]>>().toEqualTypeOf<string[]>()
263+
expectTypeOf<LogTopicType<string, Hex[]>>().toEqualTypeOf<readonly string[]>()
264264
expectTypeOf<LogTopicType<string, null>>().toEqualTypeOf<null>()
265265

266266
expectTypeOf<LogTopicType<string, Hex | null>>().toEqualTypeOf<
@@ -271,7 +271,7 @@ test('LogTopicType', () => {
271271
test('AbiEventParameterToPrimitiveType', () => {
272272
expectTypeOf<
273273
AbiEventParameterToPrimitiveType<{ name: 'foo'; type: 'string' }>
274-
>().toEqualTypeOf<string | string[] | null>()
274+
>().toEqualTypeOf<string | readonly string[] | null>()
275275
expectTypeOf<
276276
AbiEventParameterToPrimitiveType<
277277
{ name: 'foo'; type: 'string' },
@@ -286,7 +286,7 @@ test('AbiEventTopicToPrimitiveType', () => {
286286
>().toEqualTypeOf<`0x${string}`>()
287287
expectTypeOf<
288288
AbiEventTopicToPrimitiveType<{ name: 'foo'; type: 'string' }, Hex[]>
289-
>().toEqualTypeOf<`0x${string}`[][]>() // TODO: Is this correct?
289+
>().toEqualTypeOf<readonly `0x${string}`[][]>() // TODO: Is this correct?
290290
expectTypeOf<
291291
AbiEventTopicToPrimitiveType<{ name: 'foo'; type: 'string' }, null>
292292
>().toEqualTypeOf<null>()
@@ -300,7 +300,7 @@ test('AbiEventTopicToPrimitiveType', () => {
300300
>().toEqualTypeOf<boolean>()
301301
expectTypeOf<
302302
AbiEventTopicToPrimitiveType<{ name: 'foo'; type: 'bool' }, Hex[]>
303-
>().toEqualTypeOf<boolean[]>()
303+
>().toEqualTypeOf<readonly boolean[]>()
304304
})
305305

306306
test('AbiEventParametersToPrimitiveTypes', () => {
@@ -310,7 +310,7 @@ test('AbiEventParametersToPrimitiveTypes', () => {
310310
[{ name: 'foo'; type: 'string'; indexed: true }]
311311
>
312312
>().toEqualTypeOf<{
313-
foo?: string | string[] | null | undefined
313+
foo?: string | readonly string[] | null | undefined
314314
}>()
315315
expectTypeOf<
316316
AbiEventParametersToPrimitiveTypes<
@@ -321,8 +321,8 @@ test('AbiEventParametersToPrimitiveTypes', () => {
321321
]
322322
>
323323
>().toEqualTypeOf<{
324-
foo?: string | string[] | null | undefined
325-
bar?: number | number[] | null | undefined
324+
foo?: string | readonly string[] | null | undefined
325+
bar?: number | readonly number[] | null | undefined
326326
}>()
327327

328328
type Named_AllowNonIndexed = AbiEventParametersToPrimitiveTypes<
@@ -338,9 +338,9 @@ test('AbiEventParametersToPrimitiveTypes', () => {
338338
}
339339
>
340340
expectTypeOf<Named_AllowNonIndexed>().toEqualTypeOf<{
341-
foo?: string | string[] | null | undefined
342-
bar?: number | number[] | null | undefined
343-
baz?: `0x${string}` | `0x${string}`[] | null | undefined
341+
foo?: string | readonly string[] | null | undefined
342+
bar?: number | readonly number[] | null | undefined
343+
baz?: `0x${string}` | readonly `0x${string}`[] | null | undefined
344344
}>()
345345
type Named_DisableUnion = AbiEventParametersToPrimitiveTypes<
346346
[
@@ -373,8 +373,8 @@ test('AbiEventParametersToPrimitiveTypes', () => {
373373
>
374374
>().toEqualTypeOf<
375375
| readonly []
376-
| readonly [string | string[] | null]
377-
| readonly [string | string[] | null, number | number[] | null]
376+
| readonly [string | readonly string[] | null]
377+
| readonly [string | readonly string[] | null, number | readonly number[] | null]
378378
>()
379379

380380
type Unnamed_AllowNonIndexed = AbiEventParametersToPrimitiveTypes<
@@ -391,12 +391,12 @@ test('AbiEventParametersToPrimitiveTypes', () => {
391391
>
392392
expectTypeOf<Unnamed_AllowNonIndexed>().toEqualTypeOf<
393393
| readonly []
394-
| readonly [string | string[] | null]
395-
| readonly [string | string[] | null, number | number[] | null]
394+
| readonly [string | readonly string[] | null]
395+
| readonly [string | readonly string[] | null, number | readonly number[] | null]
396396
| readonly [
397-
string | string[] | null,
398-
number | number[] | null,
399-
`0x${string}` | `0x${string}`[] | null,
397+
string | readonly string[] | null,
398+
number | readonly number[] | null,
399+
`0x${string}` | readonly `0x${string}`[] | null,
400400
]
401401
>()
402402

@@ -426,7 +426,7 @@ test('AbiEventParametersToPrimitiveTypes', () => {
426426
>
427427
>().toEqualTypeOf<
428428
| readonly []
429-
| readonly [string | string[] | null]
430-
| readonly [string | string[] | null, number | number[] | null]
429+
| readonly [string | readonly string[] | null]
430+
| readonly [string | readonly string[] | null, number | readonly number[] | null]
431431
>()
432432
})

src/types/contract.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ export type LogTopicType<
466466
topic extends LogTopic = LogTopic,
467467
> = topic extends Hex
468468
? primitiveType
469-
: topic extends Hex[]
470-
? primitiveType[]
469+
: topic extends readonly Hex[]
470+
? readonly primitiveType[]
471471
: topic extends null
472472
? null
473473
: never

src/types/misc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { OneOf } from './utils.js'
33
export type ByteArray = Uint8Array
44
export type Hex = `0x${string}`
55
export type Hash = `0x${string}`
6-
export type LogTopic = Hex | Hex[] | null
6+
export type LogTopic = Hex | readonly Hex[] | null
77
export type SignableMessage =
88
| string
99
| {

0 commit comments

Comments
 (0)