@@ -68,6 +68,13 @@ export type DecoderOptions<ContextType = undefined> = Readonly<
6868 * `null` is a special value to disable the use of the key decoder at all.
6969 */
7070 keyDecoder : KeyDecoder | null ;
71+
72+ /**
73+ * A function to convert decoded map key to a valid JS key type.
74+ *
75+ * Defaults to a function that throws an error if the key is not a string or a number.
76+ */
77+ mapKeyConverter : ( key : unknown ) => MapKeyType ;
7178 } >
7279> &
7380 ContextOf < ContextType > ;
@@ -78,8 +85,11 @@ const STATE_MAP_VALUE = "map_value";
7885
7986type MapKeyType = string | number ;
8087
81- const isValidMapKeyType = ( key : unknown ) : key is MapKeyType => {
82- return typeof key === "string" || typeof key === "number" ;
88+ const mapKeyConverter = ( key : unknown ) : MapKeyType => {
89+ if ( typeof key === "string" || typeof key === "number" ) {
90+ return key ;
91+ }
92+ throw new DecodeError ( "The type of key must be string or number but " + typeof key ) ;
8393} ;
8494
8595type StackMapState = {
@@ -213,6 +223,7 @@ export class Decoder<ContextType = undefined> {
213223 private readonly maxMapLength : number ;
214224 private readonly maxExtLength : number ;
215225 private readonly keyDecoder : KeyDecoder | null ;
226+ private readonly mapKeyConverter : ( key : unknown ) => MapKeyType ;
216227
217228 private totalPos = 0 ;
218229 private pos = 0 ;
@@ -236,6 +247,7 @@ export class Decoder<ContextType = undefined> {
236247 this . maxMapLength = options ?. maxMapLength ?? UINT32_MAX ;
237248 this . maxExtLength = options ?. maxExtLength ?? UINT32_MAX ;
238249 this . keyDecoder = options ?. keyDecoder !== undefined ? options . keyDecoder : sharedCachedKeyDecoder ;
250+ this . mapKeyConverter = options ?. mapKeyConverter ?? mapKeyConverter ;
239251 }
240252
241253 private clone ( ) : Decoder < ContextType > {
@@ -631,14 +643,11 @@ export class Decoder<ContextType = undefined> {
631643 continue DECODE;
632644 }
633645 } else if ( state . type === STATE_MAP_KEY ) {
634- if ( ! isValidMapKeyType ( object ) ) {
635- throw new DecodeError ( "The type of key must be string or number but " + typeof object ) ;
636- }
637646 if ( object === "__proto__" ) {
638647 throw new DecodeError ( "The key __proto__ is not allowed" ) ;
639648 }
640649
641- state . key = object ;
650+ state . key = this . mapKeyConverter ( object ) ;
642651 state . type = STATE_MAP_VALUE ;
643652 continue DECODE;
644653 } else {
0 commit comments