Skip to content

Conversation

@witemple-msft
Copy link
Member

This PR implements fn in TypeSpec. Functions are like decorators in that they are callable entities bound to implementations through the TypeSpec JavaScript host function interface.

Functions are declared using extern fn and must bind to an implementation declared through a $functions export in a JS source file.

Functions accept and produce entities. Value arguments to functions are converted to JS values like decorator arguments are, and the inverse is also true for functions: returned JS values are converted to TSP Value entities through an "unmarshaling" process. This allows the implementation to be natural for JS developers while integrating with the TSP value space.

Functions can have a return type constraint. The default return type constraint of a function, if none is specified, is unknown. Functions can also return void, in which case JS functions that return undefined are specially accepted as if they returned voidType. This allows JS void functions to bind naturally to TypeSpec functions that return void.

Functions calls are evaluated at check-time. When a CallExpression is checked, where the callee is an instance of FunctionType:

  • We first check the arguments to the function for compatibility with the functions signature.
  • We marshal the arguments to JS if necessary.
  • We call the underlying implementation to get the value it returns.
  • We unmarshal the return value to TypeSpec if necessary.
  • We check the unmarshaled entity for assignability to the return constraint.
  • The CallExpression checking result is the unmarshaled entity.

Functions support mixed constraints (Type | valueof Type) in both parameter and return position.

Like decorators, functions cannot serve as regular types and are only allowed to appear when resolving the target of a CallExpression. model Foo { p: f } where f is a FunctionType is not allowed, but model Foo { p: f() } is.

Unlike decorators, function host bindings MUST use $functions. Bare exported functions are not bound to JS source files.

Functions appear in the type graph as functionDeclarations on a Namespace. The semantic walker has been updated to visit FunctionType declarations.

TSPD is updated to generate extern signatures for functions, like decorators.

This PR also adds an unknown value kind. The unknown value denotes the presence of a value that is not known (e.g. because the service author simply did not wish to specify what the value is, or because the service author cannot specify what it is because it depends on unknown runtime factors such as region, server time, etc.). The unknown value is also used as a moral equivalent of errorType in value space. It cannot be passed to decorator or function implementations, and it cannot be serialized to JSON. The OpenAPI3 emitter has been updated to ignore the presence of UnknownValue in default position.

@github-actions
Copy link
Contributor

All changed packages have been documented.

  • @typespec/compiler
  • @typespec/events
  • @typespec/html-program-viewer
  • @typespec/http-client
  • @typespec/http
  • @typespec/json-schema
  • @typespec/openapi
  • @typespec/openapi3
  • @typespec/protobuf
  • @typespec/rest
  • @typespec/spector
  • @typespec/sse
  • @typespec/streams
  • @typespec/tspd
  • @typespec/versioning
  • @typespec/xml
Show changes

@typespec/compiler - feature ✏️

Added support for Functions, a new type graph entity and language feature. Functions enable library authors to provide input-output style transforms that operate on types and values. See the Functions Documentation for more information about the use and implementation of functions.,> ,> Added an unknown value that can be used to denote when a property or parameter has a default value, but its value cannot be expressed in TypeSpec (for example, because it depends on the server instance where it is generated, or because the service author simply does not with to specify how the default value is generated). This adds a new kind of Value to the language that represents a value that is not known.

@typespec/openapi3 - feature ✏️

Updated emitter logic to ignore unknown values in parameter and schema property defaults.

@typespec/events - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/html-program-viewer - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/http-client - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/http - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/json-schema - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/openapi - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/protobuf - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/rest - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/spector - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/sse - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/streams - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/tspd - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/versioning - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@typespec/xml - internal ✏️

Updated tspd to generate extern function signatures. Regenerated all extern signatures.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 21, 2025

Open in StackBlitz

@typespec/compiler

npm i https://pkg.pr.new/microsoft/typespec/@typespec/compiler@9060

@typespec/events

npm i https://pkg.pr.new/microsoft/typespec/@typespec/events@9060

@typespec/html-program-viewer

npm i https://pkg.pr.new/microsoft/typespec/@typespec/html-program-viewer@9060

@typespec/http

npm i https://pkg.pr.new/microsoft/typespec/@typespec/http@9060

@typespec/http-client

npm i https://pkg.pr.new/microsoft/typespec/@typespec/http-client@9060

@typespec/json-schema

npm i https://pkg.pr.new/microsoft/typespec/@typespec/json-schema@9060

@typespec/openapi

npm i https://pkg.pr.new/microsoft/typespec/@typespec/openapi@9060

@typespec/openapi3

npm i https://pkg.pr.new/microsoft/typespec/@typespec/openapi3@9060

@typespec/protobuf

npm i https://pkg.pr.new/microsoft/typespec/@typespec/protobuf@9060

@typespec/rest

npm i https://pkg.pr.new/microsoft/typespec/@typespec/rest@9060

@typespec/spector

npm i https://pkg.pr.new/microsoft/typespec/@typespec/spector@9060

@typespec/sse

npm i https://pkg.pr.new/microsoft/typespec/@typespec/sse@9060

@typespec/streams

npm i https://pkg.pr.new/microsoft/typespec/@typespec/streams@9060

@typespec/tspd

npm i https://pkg.pr.new/microsoft/typespec/@typespec/tspd@9060

@typespec/versioning

npm i https://pkg.pr.new/microsoft/typespec/@typespec/versioning@9060

@typespec/xml

npm i https://pkg.pr.new/microsoft/typespec/@typespec/xml@9060

commit: f62f80d

@azure-sdk
Copy link
Collaborator

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants