v2.2.0

IResult

Generic operation-result interface. Implemented by Result<T> and (transitively) by AjaxResult<T>.

IResult<T> captures the success-flag-plus-data-plus-error-bag pattern used throughout the SDK. Concrete classes:

T defaults to unknown, not any (since 3.0.0, #279). Naming the payload is what makes the rest of the read type-checked — every action takes a generic (call.make<T>, batch.make<T>, callList.make<T>). Reading a field off an un-narrowed Result is a compile error, which is the point.

Shape

interface IResult<T = unknown> {
  readonly isSuccess: boolean
  readonly errors: Map<string, Error>

  setData(data: T | null | undefined): IResult<T>
  getData(): T | null | undefined

  addError(error: Error | string, key?: string): IResult<T>
  addErrors(errors: (Error | string)[]): IResult<T>
  getErrors(): IterableIterator<Error>
  getErrorMessages(): string[]
  getErrorsByKey(): Record<string, Error>
  getErrorMessagesByKey(): Record<string, string>
  hasError(key: string): boolean

  toString(): string
}

Every mutator returns the result itself, parameterised with the same T — so a chain keeps the payload type. Until v2.2.0 addError / addErrors were declared as returning a bare IResult (that is, IResult<any>), which silently degraded getData() to any for anything read after a chained call.

AjaxResult<T> narrows setData to never (immutable response), and overrides getData() to return SuccessPayload<T> when isSuccess.

Typical Usage Pattern

import type { IResult } from '@bitrix24/b24jssdk'

function consume<T>(result: IResult<T>) {
  if (!result.isSuccess) {
    for (const message of result.getErrorMessages()) {
      console.error(message)
    }
    return
  }
  const data = result.getData()
  // ...
}