Skip to main content

Overview

Maps a Result<T, E> to Result<T, F> by applying a function to a contained Err value, leaving an Ok value untouched. This is useful for transforming error values, such as converting low-level errors to user-friendly messages.

Signature

class Result<T, E> {
  mapErr<U>(f: (e: E) => U): Result<T, U>
}

Parameters

f
(e: E) => U
required
A function that transforms the Err value from type E to type U. This function is only called if the Result is Err.

Returns

Returns a new Result<T, U> where:
  • If the original Result is Ok(value), returns Ok(value) unchanged
  • If the original Result is Err(error), returns Err(f(error))

Examples

Basic Error Transformation

import { err, ok } from 'neverthrow'

const errVal = err('Round 1, Fight!')
const mapped = errVal.mapErr((error: string) => 
  error.replace('1', '2')
)

mapped.isErr() // true
mapped._unsafeUnwrapErr() // 'Round 2, Fight!'

Skips Ok Values

const okVal = ok(12)
const mapErrorFunc = (error: string) => 'mapped error value'

const notMapped = okVal.mapErr(mapErrorFunc)

notMapped.isOk() // true
// mapErrorFunc was never called

Convert Low-Level Errors

import { parseHeaders } from 'imaginary-http-parser'
// parseHeaders(raw: string): Result<Headers, ParseError>

const rawHeaders = 'nonsensical gibberish'
const parseResult = parseHeaders(rawHeaders)

const userFriendly = parseResult.mapErr(parseError => ({
  status: 400,
  message: 'Invalid headers format',
  details: parseError.message
}))

Error Type Conversion

type DatabaseError = { code: string; details: string }
type ApiError = { statusCode: number; message: string }

const dbResult: Result<User, DatabaseError> = err({
  code: 'DB_001',
  details: 'Connection timeout'
})

const apiResult: Result<User, ApiError> = dbResult.mapErr(
  (dbErr) => ({
    statusCode: 500,
    message: `Database error: ${dbErr.code}`
  })
)

Chaining Error Transformations

const result = err(404)
  .mapErr((code) => `Error ${code}`)           // Err('Error 404')
  .mapErr((msg) => msg.toUpperCase())          // Err('ERROR 404')
  .mapErr((msg) => new Error(msg))             // Err(Error('ERROR 404'))

Real-World HTTP Example

enum DatabaseError {
  NotFound = 'NotFound',
  Timeout = 'Timeout',
  Unauthorized = 'Unauthorized'
}

function queryUser(id: string): Result<User, DatabaseError> {
  // ... database query
}

const result = queryUser('123').mapErr((dbError) => {
  switch (dbError) {
    case DatabaseError.NotFound:
      return { status: 404, message: 'User not found' }
    case DatabaseError.Timeout:
      return { status: 504, message: 'Database timeout' }
    case DatabaseError.Unauthorized:
      return { status: 403, message: 'Access denied' }
  }
})

Implementation Details

From the source code (result.ts:435-437):
mapErr<U>(f: (e: E) => U): Result<T, U> {
  return err(f(this.error))
}
For Ok (result.ts:328-330):
mapErr<U>(_f: (e: E) => U): Result<T, U> {
  return ok(this.value)
}

Notes

  • The mapping function is only executed for Err values
  • The success type T remains unchanged
  • This method does not catch exceptions thrown by the mapping function
  • Useful for error normalization across different layers of your application
  • Can be combined with .map() to transform both success and error paths

Build docs developers (and LLMs) love