Typed Hooks

OCAPI, SCAPI, and order hooks registered in hooks.json get typed parameters and return values automatically, with no JSDoc in your hook scripts

Register a hook in hooks.json and its implementation is typed for you. The language server knows the signatures of 86 system hooks, so in a basket hook basket is a dw.order.Basket and a wrong return value is an error. Your file stays plain JavaScript

hooks.json registers basket.js for dw.ocapi.shop.basket.modifyGETResponse. With no JSDoc in the file, basket is typed as a Basket, its members complete, and a wrong return value is an error

What you get

In the hook functionResult
Hover a parameterIts SFCC type, for example basket: Basket
Type basket.Every Basket member with its API docs
Return the wrong valueAn error such as Type 'boolean' is not assignable to type 'Status'
Call an API methodSignature help and argument checks, for example on basket.getShipment()

Typed hook families

SCAPI Shopper APIs run the same dw.ocapi.shop.* hooks as OCAPI, so one implementation gets the same types for both

HooksCountTyped parameters
dw.ocapi.shop.basket.*35basket: dw.order.Basket, plus the request or response document. Covers the basket, items, coupons, payment instruments, billing address, and shipments
dw.ocapi.shop.customer.*11customer: dw.customer.Customer, address names, and documents
dw.ocapi.shop.order.*8order: dw.order.Order and the order response
dw.ocapi.shop.auth.*3customer: dw.customer.Customer, authRequestType: dw.value.EnumValue
dw.ocapi.shop.product.*, category.*, product_search.*6dw.catalog.Product, dw.catalog.Category, and the response document
dw.order.calculate, calculateShipping, calculateTax, createOrderNo4basket: dw.order.Basket; createOrderNo returns a string
dw.order.payment.*, return.*, shippingorder.*10dw.order.Order, Invoice, Return, and ShippingOrder
dw.system.request.onRequest, onSession2Return type only
dw.extensions.applepay.*7basket: dw.order.Basket, order: dw.order.Order

Most hooks return dw.system.Status. Request and response documents (basketResponse, doc, and similar) are typed as plain objects, so any property you add is accepted

How the types are applied

Register the hook. The hooks.json your cartridge's package.json points to maps the hook name to a script. That registration is what links the file to a known signature

Export the function. Write exports.modifyGETResponse = function (basket, basketResponse) { … }, the module.exports.modifyGETResponse form or an arrow function. The function name must match the hook's last segment. A function that several hooks share, such as one beforePATCH for baskets and orders, takes the types of all of them, like dw.order.Basket | dw.order.Order

Edit as usual. The server adds the signature as JSDoc in its in-memory copy of the file. Your parameter names are kept, and types are applied by position

When types are not applied

  • You wrote JSDoc. A /** … */ block above the export wins, so your own annotation is used instead
  • Other export shapes. module.exports = { … } and exports.name = namedFunction are not typed. Use exports.name = function (…) {}
  • Custom hooks. Your own hook names have no known signature. Add JSDoc or write the hook in TypeScript
  • Hooks outside the list. For example the bare dw.ocapi.shop.basket.beforePOST (the _v2 variant is typed). Add JSDoc for those

On this page