Skip to content

Expressions

Composable expression references and factory methods for TypeScript code generation.

See also: Overview | Emit | Types | Core Expressions


TsExpressionRef

The expression-domain counterpart to TsTypeRef. A composable, immutable readonly record struct representing anything valid on the right side of an assignment.

using Deepstaging.Roslyn.TypeScript;

A TsTypeRef crosses into expression domain via gateway methods (New, Call, Member). Once in expression domain, chaining continues through TsExpressionRef methods. This is a one-way gate — same as the C# layer.

Method Calls and Member Access

TsExpressionRef.From("items")
    .Call("filter", "x => x > 0")
    .Call("map", "x => x * 2")
    // items.filter(x => x > 0).map(x => x * 2)

TsExpressionRef.From("fetch").Invoke("url")
    // fetch(url)

TsExpressionRef.From("user").Member("name")
    // user.name

TsExpressionRef.From("items").Index("0")
    // items[0]
Method Description Output
.Call(method, args...) Method call expr.method(args)
.Invoke(args...) Function invocation expr(args)
.Member(name) Property access expr.name
.Index(key) Computed access expr[key]

Optional Chaining and Nullish Coalescing

TypeScript's ?. and ?? operators for safe navigation.

TsExpressionRef.From("user")
    .OptionalChain("address")
    .OptionalChain("city")
    .NullishCoalesce("\"unknown\"")
    // user?.address?.city ?? "unknown"

TsExpressionRef.From("handler")
    .OptionalCall("process", "data")
    // handler?.process(data)

TsExpressionRef.From("items")
    .OptionalIndex("0")
    // items?.[0]
Method Description Output
.OptionalChain(name) Optional member access expr?.name
.OptionalCall(method, args...) Optional method call expr?.method(args)
.OptionalIndex(index) Optional element access expr?.[index]
.NullishCoalesce(fallback) Nullish coalescing expr ?? fallback
.NonNullAssertion() Non-null assertion expr!

Type Assertions and Checks

TsExpressionRef.From("value").As("string")          // value as string
TsExpressionRef.From("config").Satisfies("Config")  // config satisfies Config
TsExpressionRef.From("value").TypeOf()               // typeof value
TsExpressionRef.From("err").InstanceOf("Error")      // err instanceof Error
Method Description Output
.As(type) Type assertion expr as Type
.Satisfies(type) Satisfies check expr satisfies Type
.TypeOf() typeof operator typeof expr
.InstanceOf(type) instanceof check expr instanceof Type

Async, Spread, and Template Literals

TsExpressionRef.From("fetch").Invoke("url").Await()
    // await fetch(url)

TsExpressionRef.From("args").Spread()
    // ...args

TsExpressionRef.From("name").TemplateLiteral("Hello, ", "!")
    // `Hello, ${name}!`

Logical Operators

TsExpressionRef.From("a").StrictEquals("b")       // a === b
TsExpressionRef.From("a").StrictNotEquals("b")    // a !== b
TsExpressionRef.From("a").And("b")                // a && b
TsExpressionRef.From("a").Or("b")                 // a || b
TsExpressionRef.From("valid").Not()               // !valid
TsExpressionRef.From("expr").Parenthesize()       // (expr)

Implicit Conversions

TsExpressionRef converts implicitly to and from string, and from TsTypeRef (a type name is a valid expression):

TsExpressionRef e = "myVar";                // implicit from string
string s = e.Call("toString");               // implicit to string
TsExpressionRef t = TsTypeRef.From("Math"); // implicit from TsTypeRef

Expression Factories

Static classes that produce TsExpressionRef for common TypeScript patterns. These mirror TaskExpression, CollectionExpression, etc. from the C# layer.

using Deepstaging.Roslyn.TypeScript.Expressions;

TsPromiseExpression

TsPromiseExpression.Resolve("value")            // Promise.resolve(value)
TsPromiseExpression.Reject("reason")            // Promise.reject(reason)
TsPromiseExpression.All(a, b, c)                // Promise.all([a, b, c])
TsPromiseExpression.AllSettled(a, b)             // Promise.allSettled([a, b])
TsPromiseExpression.Race(a, b)                   // Promise.race([a, b])
TsPromiseExpression.Any(a, b)                    // Promise.any([a, b])
TsPromiseExpression.New("(resolve, reject) => { ... }")
                                                  // new Promise((resolve, reject) => { ... })

TsJsonExpression

TsJsonExpression.Stringify("data")               // JSON.stringify(data)
TsJsonExpression.Parse("text")                    // JSON.parse(text)

TsFetchExpression

TsFetchExpression.Get("url")                     // fetch(url)
TsFetchExpression.Post("url", "body")            // fetch(url, { method: 'POST', body: ... })

TsConsoleExpression

TsConsoleExpression.Log("msg")                   // console.log(msg)
TsConsoleExpression.Error("msg")                 // console.error(msg)
TsConsoleExpression.Warn("msg")                  // console.warn(msg)

TsArrayExpression

TsArrayExpression.From("iterable")              // Array.from(iterable)
TsArrayExpression.Of(a, b, c)                   // [a, b, c]
TsArrayExpression.IsArray("value")              // Array.isArray(value)

TsObjectExpression

TsObjectExpression.Keys("obj")                  // Object.keys(obj)
TsObjectExpression.Values("obj")                // Object.values(obj)
TsObjectExpression.Entries("obj")               // Object.entries(obj)
TsObjectExpression.Assign("target", "source")   // Object.assign(target, source)
TsObjectExpression.Freeze("obj")                // Object.freeze(obj)

TsErrorExpression

TsErrorExpression.New("message")                 // new Error(message)
TsErrorExpression.NewType("TypeError", "msg")    // new TypeError(msg)

Composing Types and Expressions

A typical source generator pattern — analyze a Roslyn symbol, then build TypeScript output using both type refs and expressions:

using Deepstaging.Roslyn.TypeScript;
using Deepstaging.Roslyn.TypeScript.Emit;
using Deepstaging.Roslyn.TypeScript.Types;
using Deepstaging.Roslyn.TypeScript.Expressions;

// Build type refs for the service
var promiseType = new TsPromiseTypeRef("User[]");
var mapType = new TsMapTypeRef("string", "User");

// Build the service class
var result = TsTypeBuilder.Class("UserService")
    .Exported()
    .AddField("cache", mapType, f => f
        .WithAccessibility(TsAccessibility.Private)
        .AsReadonly()
        .WithInitializer("new Map()"))
    .AddMethod("fetchUsers", m => m
        .Async()
        .WithReturnType(promiseType)
        .WithBody(b => b
            .AddConst("response", TsExpressionRef.From("fetch").Invoke("'/api/users'").Await())
            .AddConst("data", TsExpressionRef.From("response").Call("json").Await())
            .AddReturn("data")))
    .AddMethod("logCache", m => m
        .WithReturnType("void")
        .WithBody(b => b
            .AddStatement(TsConsoleExpression.Log("this.cache"))))
    .Emit();