# Decode errors
All decoders from @apoyo/decoders will return a Result<Type, DecodeError>, where Type contains the type of the decoded value, and DecodeError being the validation error.
In this post, we will look in more details at all possible validation errors:
# Values
DecodeError.Value errors represents an error for a single value:
export namespace DecodeError {
  // ...
  export interface Value {
    _tag: 'DE.Value'
    value: unknown
    message: string
    meta: Dict
  }
}
Examples:
- The input is not a valid number
 - The input is not an object
 - etc...
 
As such, it is most of the time similar to "leafs" in tree-like structures.
This type of error contains the original (invalid) value and an error message. It may also contain additional metadata (error codes, etc...)
# Arrays (and array-likes)
DecodeError.ArrayLike and DecodeError.Index are used to represent errors for array-like structures:
export namespace DecodeError {
  // ...
  export interface Index {
    _tag: 'DE.Index'
    index: number
    error: DecodeError
  }
  export interface ArrayLike {
    _tag: 'DE.ArrayLike'
    kind: string // "array" is used for Array decoders
    errors: DecodeError.Index[]
  }
}
An invalid array will return an DecodeError.ArrayLike error.
This DecodeError.ArrayLike error will contain a list of DecodeError.Index errors.
Each DecodeError.Index will contain a reference to the original DecodeError.Value and the index at which the error occured.
Note: You could also use these error types to represent errors for tuple types.
# Objects (and object-likes)
DecodeError.ObjectLike and DecodeError.Key are used to represent errors for object-like structures:
export namespace DecodeError {
  // ...
  export interface Key {
    _tag: 'DE.Key'
    key: string
    error: DecodeError
  }
  export interface ObjectLike {
    _tag: 'DE.ObjectLike'
    kind: string // "object" is used for Object decoders
    name?: string
    errors: DecodeError.Key[]
  }
}
An invalid array will return an DecodeError.ObjectLike error.
This DecodeError.ObjectLike error will contain a list of DecodeError.Key errors.
Each DecodeError.Key will contain a reference to the original DecodeError.Value and the name of the property at which the error occured.
Note: You could also use these error types to represent errors for Map<string, any> types.
# Unions (and union-likes)
DecodeError.UnionLike and DecodeError.Member are used to represent errors for union-like types:
export namespace DecodeError {
  // ...
  export interface Member {
    _tag: 'DE.Member'
    index: number
    error: DecodeError
  }
  export interface UnionLike {
    _tag: 'DE.UnionLike'
    kind: string // "union" is used for unions
    name?: string
    errors: DecodeError.Member[]
  }
}
Unions are used to check if an input matches one of the given types.
Example: The input is either a number, or a string, or a boolean.
To validate these kind of structures, the decoder goes, one by one, through the list of decoders:
const bool = Decoder.union(
  BooleanDecoder.boolean,
  BooleanDecoder.fromString,
  BooleanDecoder.fromNumber
)
If all decoders are invalid, an DecodeError.UnionLike error is returned.
This DecodeError.UnionLike error will contain a list of DecodeError.Member errors, one for each possible type in the union.
Each DecodeError.Member will contain a reference to the original DecodeError.Value and the name of the index at which the error occured.
Note: You could also use these error types to represent errors for intersection types.
# Error reporters
By default, @apoyo/decoders provide 2 ways to format these errors:
DecodeError.draw: By transforming aDecodeErrorinto aTree, we can draw an error an obtain a printable string like the following:
array
├─ index 0
│  └─ cannot decode "test": value is not a number
└─ index 1
   └─ cannot decode "another": value is not a number
DecodeError.flatten: By flattening all errors to obtain the path to the invalid value.
export interface Flat {
  value: unknown
  message: string
  meta: Dict
  ...
}
Note: When using unions, the flattened list of errors may contain multiple times properties for the same path, but for a different union member.
Example: For the given decoder below, you may receive an error twice for the path 'type', if the type is neither 'Ok' or 'Ko':
const Ok = ObjectDecoder.struct({
  type: TextDecoder.equals('Ok'),
  ok: Decoder.unknown
})
const Ko = z.object({
  type: TextDecoder.equals('Ko'),
  ko: Decoder.unknown
})
const Result = Decoder.union(Ok, Ko)