Calling RedM/RDR3 natives from JavaScript / TypeScript
Reference for translating native docs (which contain Lua examples) into JS/TS calls.
TL;DR
// void return
Citizen.invokeNative('0xHASH', arg1, arg2);
// typed return — append a result modifier as the LAST argument
const n = Citizen.invokeNative('0xHASH', arg1, Citizen.resultAsInteger());
const f = Citizen.invokeNative('0xHASH', arg1, Citizen.resultAsFloat());
const s = Citizen.invokeNative('0xHASH', arg1, Citizen.resultAsString());
const v = Citizen.invokeNative('0xHASH', arg1, Citizen.resultAsVector()); // {x,y,z}
The result modifier is what selects the return type. Without one, the result is unusable for non-void natives.
Two invokeNative variants
| Form | Signature | When |
|---|---|---|
Citizen.invokeNative |
(hash: string, ...args) => T |
Default. Use this. |
Citizen.invokeNativeByHash |
(hashLo: number, hashHi: number, ...args) => T |
Used by official codegen for perf. Hash split into two 32-bit ints: hashLo = hash & 0xFFFFFFFF, hashHi = hash >>> 32. Rarely needed by hand. |
Both accept the same result modifiers. Prefer invokeNative with the string hash unless you have a specific reason.
Return-type → result modifier
| Native return type | Modifier | JS value |
|---|---|---|
void |
(none) | — |
int, BOOL, Hash, Entity, Ped, Vehicle, Object, Cam, Blip, Pickup |
Citizen.resultAsInteger() |
number |
float |
Citizen.resultAsFloat() |
number |
const char*, char* |
Citizen.resultAsString() |
string |
Vector3 |
Citizen.resultAsVector() |
{ x: number, y: number, z: number } |
long, pointer, 64-bit handle |
Citizen.resultAsLong() |
number (use with care for 64-bit) |
| object / table-like | Citizen.resultAsObject2() |
object |
BOOL returns 0 or 1 — coerce with !! if you want a real boolean.
Argument-type mapping
| Native param type | JS arg |
|---|---|
int, BOOL, Hash, Entity, Ped, Vehicle, Object |
number |
float |
number |
const char* |
string |
Vector3 |
Pass three separate args: x, y, z — not an object |
Hash from a name |
GetHashKey('model_name') |
Any*, int*, float*, Vector3* (output pointers) |
See Pointer args below |
Pointer args (output parameters)
Many natives return extra values via pointer arguments (e.g. GET_GROUND_Z_FOR_3D_COORD writes the ground Z into a float*).
In JS, pass 0 (or any number) as a placeholder — the runtime allocates and returns the value. To read it, you must use the Cfx output-arg trick with multiple result modifiers, or use a wrapper resource. Pure manual invokeNative with output pointers is awkward; check if a wrapper exists first (e.g. via @nativewrappers/fivem or community type defs).
If unavoidable:
// pseudocode — exact pattern depends on the native; verify on a forum/source
const [hit, groundZ] = Citizen.invokeNative(
'0x9E82F0F362881B29',
x, y, z,
0, // float* outGroundZ — placeholder
Citizen.resultAsInteger() // returns BOOL
);
When in doubt, flag it as a manual translation rather than guessing parameter order.
Worked examples > void, no return
Lua doc says:
DisableScriptBrainSet(brainSet)
Citizen.InvokeNative(0x3F44EA613A5B2676, brainSet)
JS:
Citizen.invokeNative('0x3F44EA613A5B2676', brainSet);
Worked examples > int return
GetPlayerPed → returns Ped (int).
const ped = Citizen.invokeNative('0x275F255ED201B937', playerId, Citizen.resultAsInteger());
Worked examples > float return
GetEntityHeading → returns float.
const heading = Citizen.invokeNative('0xE83D4F9BA2A38914', entity, Citizen.resultAsFloat());
Worked examples > string return
GetEntityModel returning a const char*:
const name = Citizen.invokeNative('0x...', entity, Citizen.resultAsString());
Worked examples > Vector3 return
GetEntityCoords → returns Vector3.
const coords = Citizen.invokeNative('0xA86D5F069399F44D', entity, true, Citizen.resultAsVector());
// coords.x, coords.y, coords.z
Worked examples > Vector3 as argument
SET_ENTITY_COORDS(entity, x, y, z, ...) — pass components separately:
Citizen.invokeNative('0x06843DA7060A026B', entity, x, y, z, false, false, false, false);
Common gotchas
- No modifier → garbage return. A non-void native called without a
resultAs…()will not produce a usable value. - Wrong modifier → silently wrong type.
resultAsInteger()on a float native returns the IEEE-754 bit pattern reinterpreted as int. Match the modifier to the documented return type. BOOLisnumber.resultAsInteger()then coerce:const ok = !!Citizen.invokeNative(...);- Hash strings are case-insensitive but
'0x'-prefixed. Both'0xABCD...'and'0xabcd...'work. - Lua
Citizen.InvokeNativeis capital-I; JSCitizen.invokeNativeis lowercase-i. Easy typo. - Pointer outputs are not auto-unwrapped like in Lua. Treat any native with
*parameters as needing manual verification.
When the docs only show Lua
Every native page in this server has Lua examples (Direct + Hash form). Translate by:
- Copy the hash from the Lua
Citizen.InvokeNative(0xHASH, …)line. - Look up the Return Type row in the native's table.
- Pick the matching modifier from the table above (or omit for
void). - Pass args in the same order as Lua, with the type mapping above.
- Append the modifier as the last argument.