Skip to content

Typed events example

Define the server-side event maps through module augmentation:

ts
import '@vimp-mp/types/server'

declare module '@vimp-mp/types/server' {
  interface VimpServerEvents {
    'garage:spawn': { model: string }
    'profile:ready': { nickname: string }
  }

  interface VimpClientInboundEvents {
    'garage:spawned': { vehicleId: number }
    'hud:toast': { text: string }
  }
}

The server receives the sender and validated payload:

ts
vimp.on('garage:spawn', (player, payload) => {
  const vehicle = vimp.vehicles.create(
    vimp.hash(payload.model),
    94.5,
    -1940.2,
    20.7,
    307,
    { numberPlate: 'VIMP', engineOn: true },
  )

  if (vehicle) {
    player.emit('garage:spawned', { vehicleId: vehicle.id })
  }
})

Declare the same transport shapes in the client context:

ts
import '@vimp-mp/types/client'

declare module '@vimp-mp/types/client' {
  interface VimpClientEvents {
    'garage:spawned': { vehicleId: number }
    'hud:toast': { text: string }
    'ui:ready': { mountedAt: number }
  }

  interface VimpServerInboundEvents {
    'garage:spawn': { model: string }
    'profile:ready': { nickname: string }
  }
}
ts
vimp.on('garage:spawned', ({ vehicleId }) => {
  vimp.notify(`Vehicle #${vehicleId} is ready`)
})

vimp.emitServer('profile:ready', { nickname: 'ViceRider' })

TypeScript checks both directions at build time. The server must still validate runtime payload values and permissions because a modified client can bypass compile-time types.

VIMP developer documentation