Chains with LCEL: Composing Runnables in TypeScript
LCEL (LangChain Expression Language) composes in TypeScript the same way it does in Python, except instead of the | operator (which TypeScript doesn't let you overload), LangChain.js uses an explicit .pipe() method to chain Runnables together.
Building a chain with .pipe()
This needs a real API key, so it's read-only here. prompt.pipe(model).pipe(parser) reads left to right, exactly like Python's prompt | model | parser: the input object flows into prompt, its output flows into model, and the model's response flows into parser, which extracts a plain string. result is typed as string, not a message object you'd need to unwrap.
Batching
Also read-only here, since it calls the model. Because chain is itself a Runnable, it gets .batch() (many inputs) and .stream() (token-by-token output) automatically, the same three methods every piece in the pipeline already had.
Why types matter here
Each piece in a .pipe() chain is generically typed by its input and output, ChatPromptTemplate outputs a message type that ChatOpenAI accepts as input, and StringOutputParser narrows that model's response down to string. If you tried to pipe two incompatible pieces together, TypeScript's compiler catches the mismatch before you ever run the code, one of the concrete advantages of building LLM chains in a typed language.
NOTE
.pipe() and Python's | do exactly the same thing: build a new Runnable from smaller ones. The syntax differs because operator overloading isn't available in TypeScript, the composition model underneath is identical.