Skip to content

Latest commit

 

History

History
179 lines (137 loc) · 5.19 KB

typescript.md

File metadata and controls

179 lines (137 loc) · 5.19 KB

TypeScript

The API is fully typed for TypeScript users (>= 4.7).

Since this package is an ES module, TypeScript must be configured to output ES modules, not CommonJS.

Error properties and methods

Error classes' and instances' props, aggregate errors and custom methods/properties are typed.

const BaseError = ModernError.subclass('BaseError', {
  props: { userId: 5 as const },
  custom: class extends ModernError {
    isUserInput() {
      return true as const
    }
  },
})
const error = new BaseError('Wrong user name', {
  props: { userName: 'Alice' as const },
})
const { userId, userName } = error // Inferred type: `5` and `"Alice"`
const result = error.isUserInput() // Inferred type: `true`

Error props without default values can also be typed.

const BaseError = ModernError.subclass('BaseError', {
  props: {} as { userId: number },
})

type UserId = InstanceType<typeof BaseError>['userId'] // Type: `number`

Custom options

custom options can be typed.

import type { InstanceOptions } from 'modern-errors'

interface InputErrorOptions {
  suffix?: string
}

export const InputError = BaseError.subclass('InputError', {
  custom: class extends BaseError {
    constructor(
      message: string,
      options?: InstanceOptions & InputErrorOptions,
    ) {
      message += options?.suffix ?? ''
      super(message, options)
    }
  },
})

// Type error: `suffix` must be a string
const error = new InputError('Wrong user name', { suffix: true })

Plugins

Plugin methods, properties and options are typed.

import ModernError from 'modern-errors'
// This plugin adds a `BaseError.httpResponse(error)` method
import modernErrorsHttp from 'modern-errors-http'

const BaseError = ModernError.subclass('BaseError', {
  plugins: [modernErrorsHttp],
})

const error = new BaseError('Wrong user name', {
  http: { title: false }, // Type error: `title` must be a string
})
const httpResponse = BaseError.httpResponse(error) // Inferred type: response object

Narrowing

When catching exceptions, their type can be narrowed using instanceof.

const InputError = BaseError.subclass('InputError', {
  props: { isUserError: true as const },
})

try {
  // ...
} catch (error) {
  // Narrows `error` type to `InputError`
  if (error instanceof InputError) {
    const { isUserError } = error // Inferred type: `true`
  }
}

Type inference

Types are automatically inferred: no explicit type declaration is needed. typeof, ReturnType, etc. can be used to retrieve the type of a variable or method.

typeof ExampleError returns the error class type, while InstanceType<typeof ExampleError> (not ExampleError) returns the error instance type.

type AnyErrorClass = ReturnType<typeof BaseError.subclass>

const InputError = BaseError.subclass('InputError')
type InputErrorClass = typeof InputError

type InputErrorInstance = InstanceType<InputErrorClass>

const printErrorClass = (ErrorClass: AnyErrorClass) => {
  // ...
}

const printInputErrorClass = (InputErrorClass: InputErrorClass) => {
  // ...
}

const logInputError = (inputError: InputErrorInstance) => {
  // ...
}

printErrorClass(InputError)
printInputErrorClass(InputError)
logInputError(new InputError('Wrong user name'))

Wide types

The following types are exported: ErrorInstance, ErrorClass, ClassOptions, InstanceOptions, MethodOptions, Plugin and Info.

Those types are wide: they do not include any information about specific props, aggregate errors nor custom methods/properties. However, they can include specific plugins' methods, properties and options by passing those as a generic parameter, such as ErrorClass<[typeof plugin]>.

They should only be used to type unknown error instances and classes, when no variable nor type inference is available. For example, they can be useful when creating plugins.

Known limitations and issues

For known limitations and issues related to TypeScript's current capabilities, please see the comments in src/main.d.ts.