IResult<T> captures the success-flag-plus-data-plus-error-bag pattern used throughout the SDK. Concrete classes:
Result<T>— generic.AjaxResult<T>— REST-aware (immutable, paginated, decodes Bitrix24 error envelopes).
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()
// ...
}