Skip to content

JavaScript types in .NET

While automatic marshalling can conveniently convert JavaScript values to and from almost any specific .NET types, the marshaller has some limitations, particularly because the mappings between JS and .NET types can be inexact. So sometimes it is necessary for .NET code to interact directly with JavaScript types, precisely preserving all of the JavaScript type's semantics.

The JSValue type

The JSValue type represents any kind of JavaScript value. It can be undefined, null, a primitive (number, string, etc.) or an object. The value type can be checked via the JSValue.TypeOf() method, which is equivalent to the JS typeof operator. default(JSValue) is equivalent to the JS undefined value.

The JSValue type has methods for doing any kind of operation or conversion on the value, though many of those may throw a JSException if the value is not the correct type. And such an exception would be re-thrown to JS as a TypeError.

Available conversions include casting to and from .NET primitive type:

C#
JSValue jsString =
string s = (string)jsString;
JSValue jsString2 = s; // Conversions to JSValue are implicit.

Internally, a JSValue contains only two fields:

JSValue is a struct because a JavaScript value is not valid outside of its scope. (We've considered making it a ref struct but that design would have too many limitations.) Being a value-type also reduces memory allocations when passing JS values to .NET, improving interop performance.

Use a JSReference to store a JavaScript value on the heap and track it across multiple invocations.

Other JavaScript value types

A JSValue can be cast to another struct that represents a more specific value type:

C#
void CopyToStringArray(JSValue jsArray, string[] destination)
    => ((JSArray)jsArray).CopyTo(destination, 0, (value) => (string)value);

The specific value types provide properties and methods specific to their type, and are often easier to work with:

The value types all implement IEquatable<JSValue>, which evaluates JavaScript strict equality.

The .NET ToString() method of any type of JS value returns the same result as calling toString() from JavaScript.

Using JavaScript value types in .NET APIs

When exporting a .NET method to JavaScript, use JSCallbackArgs to declare a method that can accept any number of JavaScript values as arguments:

C#
[JSExport]
public JSValue ExampleWithVariableJSArgs(JSCallbackArgs args) { … }

Mixing .NET types and JS types in a method signature is also allowed:

C#
[JSExport]
public JSValue ExampleWithJSArray(string s, JSValue value, JSArray array) { … }

Released under the MIT license