Input and output types

This reference provides detailed documentation for the input and output types in TypeScript ↗ Functions.

In order to be published to the registry, a TypeScript Function must have explicit type annotations on all input parameters, and specify an explicit return type.

Note that calling external APIs from within a Typescript function is not available. To call an external API as part of an Action, use webhooks.

Currently, these are all the supported input and output types available in Functions:

Scalar types

  • boolean
  • string
  • Integer, Long, Float, and Double
    • Note that in JavaScript and TypeScript, there is only one number type. However, in order to provide further type validation and structure, we only support the above aliases that are exported from @foundry/functions-api. Import these types to use them as inputs and outputs in your Function definitions.
  • LocalDate and Timestamp types are used for temporal information.
    • As with numeric types, JavaScript natively supports a Date type. However, to distinguish between dates and timestamps, we provide more concrete types exported from @foundry/functions-api
    • LocalDate represents a calendar date, while Timestamp represents an instant in time.

Optional types

For input parameters, optional parameters are declared as varName?: <type>. For example, a Function that has an optional integer parameter named value would have a parameter value?: Integer.

Functions may declare an optional return type by specifying a type of <type> | undefined. For example, a Function that may return either an Integer or no value would have a return type of Integer | undefined.

Collections

  • Lists are supported using ES6 Arrays ↗ (e.g. string[] is a list of string values)
    • Note that nested lists are supported (e.g. Integer[][] is a list of lists of integer values)
  • Sets are supported using ES6 Sets ↗ (e.g. Set<string> is a Set of string values)
  • Maps are supported using FunctionsMap from @foundry/functions-api package. It can be declared using the FunctionsMap<K, V> notation where K is the key type and V is value type. Keys can be Scalar types or an Ontology object (e.g. FunctionsMap<Employee, string>). Values can be of any supported type.

Aggregations

Aggregations are types returned when retrieving bucketed aggregations over ontology objects, and they can be returned from Functions for use in other parts of the platform, such as in Charts in Workshop.

There are two supported aggregation types:

  • A TwoDimensionalAggregation maps from a single bucket key to a numeric value, which is represented as a Double. For example, a TwoDimensionalAggregation<string> maps from a string bucket key to a numeric value for each bucket. This could be used to represent an aggregation such as a count of employees with a specific job title.
  • A ThreeDimensionalAggregation maps from two bucket keys to a numeric value. For example, a ThreeDimensionalAggregation<string, string> maps from a string bucket key to an array of nested buckets. These nested buckets each have a string key that maps to a numeric value. This could be used to represent an aggregation such as a count of employees by each employee's job title and home office.

Both aggregation types can be returned from a Function, and will be available for use in other parts of the platform, specifically in Workshop Charts.

Aggregations can be keyed by several types:

  • boolean buckets represent values that are either true or false
  • string buckets can be used to represent categorical values
  • IRange (from @foundry/functions-api) buckets represent aggregations where the bucket key is a range of values. These can be used to represent a histogram or date axis in a chart.
    • Numeric ranges, including Integer and Double, represent bucketed aggregations on numeric values
    • Date and time ranges, including on LocalDate and Timestamp, represent bucketed aggregations on date ranges

Ontology types: Objects and Object Sets

Ontology imports

Object types must be imported into your repository before interfaces will be generated for them. Learn more about Ontology imports.

Each object type configured in your Ontology will be converted into a TypeScript interface for use in Functions code. All generated types are exported from the @foundry/ontology-api package. See the detailed documentation on the TypeScript Ontology API for further details.

  • When an Object type is used as an input type, a client that is executing the Function must pass an objectRid or object type and primary key of the object the client wishes to execute the Function against
  • When an Object type is used as an output type, a locator for the object is returned (the object type and primary key of the object)

There are two ways to pass a collection of objects into and out of a Function: concrete collections of objects such as arrays and sets, or Object Sets.

  • Passing an array or Set of objects to a Function enables executing logic over a concrete list of objects. For example, your Function can take employees: Employee[] or employees: Set<Employee> to receive an array or set of Employee objects
    • For an object array parameter, a client must pass a list of objectRids or object locators of the objects that should be loaded
  • The ObjectSet<> interface exported from @foundry/ontology-api enables passing an Object Set into a Function. For example, your Function can take employees: ObjectSet<Employee> to receive an Object Set of Employees. Object sets enable filtering, search around, and aggregation operations. Learn more about the object set API.
    • For an Object Set parameter, a client must pass an objectSetRid referring to a saved object set. The Object Set Service allows for object sets to be saved for a temporary amount of time to allow creating short-lived object sets to be used as Function parameters
Tip

Using the ObjectSet<> interface is often preferrable to an array, because it achieves better performance and allows more than 10,000 objects to be passed into the function.

Principals, Users, and Groups

A Principal represents either a Foundry user account or group. These types can be passed into a Function to allow accessing information associated with a User or Group, such as a group's name or a user's first and last name or email address. All Principal types are exported from the @foundry/functions-api package.

  • A User always has a username, and may have a firstName, lastName, or email. It also includes all fields associated with a Principal.
  • A Group has a name. It also includes all fields associated with a Principal.
  • A Principal can be either a User or a Group. You can inspect the type field to determine whether a given Principal is a User or a Group. In addition to User and Group-specific fields, a Principal has an id, realm, and dictionary of attributes.

Searching for Foundry users

In addition to having a User, Group, or Principal passed into a Function as a parameter, you can retrieve Users or Groups ad hoc by using the Users object exported from @foundry/functions-api

  • The getUserByIdAsync method takes a userId as a string and returns a Promise<User>
  • The getGroupByIdAsync method takes a groupId as a string and returns a Promise<Group>

Notifications

Notification types can be returned from a Function in order to flexibly configure notifications that should be sent in the platform. For example, you can author a Function that takes in parameters such as a User and an object type and returns a Notification with a configured message.

  • A Notification consists of two fields: a ShortNotification and EmailNotificationContent.
  • A ShortNotification represents a summarized version of the notification, which will be shown within the Foundry platform. It includes a short heading, content, and a collection of Links.
  • EmailNotificationContent represents a rich version of the notification which can be sent externally via email. It includes a subject, a body consisting of headless HTML, and a collection of Links.
  • A Link has a user-facing label and a linkTarget. The LinkTarget can be a URL, an OntologyObject, or a rid of any resource within Foundry.

For an example of how to use the Notifications API, see the how-to guide.

Custom types

You may also define custom input and output types for use in Functions. Custom types are defined as TypeScript interfaces, or can be defined as inline anonymous types.

  • The fields of a custom type may be any of the other types documented above, another custom type, or self-referential.
  • Optional fields are supported through the ? optional token or a field's type is a union with undefined.

Examples of custom types:

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import { Function, LocalDate } from "@foundry/functions-api"; import { Employee } from "@foundry/ontology-api"; interface EmployeeGraph { value: Employee; connections: EmployeeGraph[]; } interface EmployeeFilter { maxStartDate?: LocalDate; // Optional using the ? token role: string | undefined; // Optional using union of undefined } // This Function takes a named custom type as input and outputs a named custom type @Function() public myEmployeeSearchAround(root: Employee, filter: EmployeeFilter): EmployeeGraph { ... } // This Function outputs an anonymous custom type @Function() public getAverageAndMedianAge(employees: Employee[]): { average: Double, median: Integer } { ... }

Other types

  • ES6 Promises ↗ can be returned from a Function, to enable workflows where a Function is loading data asynchronously. At runtime, the Function Executor will wait for the Promise to be resolved before returning a value to the client.
    • Note that Promise types are ignored for the sake of publishing to the Function Registry, so a Function that returns a Promise<Integer> will show up in the Function Registry as simply returning an Integer

Parameter options

In addition to declaring data types for Function parameters, there are a few other options for how parameters should be handled.

Optional parameters and default values

TypeScript Functions support optional parameters and parameters with default values. If a Function parameter is optional, it will be published as such to the Function Registry, allowing clients to execute the Function without having to pass in that parameter. This can be useful for providing simple defaults for Functions that can be overridden for specific use cases.

Here is an example Function with an optional parameter:

Copied!
1 2 3 4 5 6 7 8 9 10 @Edits(Ticket) @OntologyEditFunction() public updateDueDate(ticket: Ticket, dueDate?: LocalDate): void { if (dueDate) { ticket.dueDate = dueDate; } else { // By default, set due date to next week ticket.dueDate = LocalDate.now().plusDays(7); } }

Here is an example Function with a default value:

Copied!
1 2 3 4 @Function() public computeRiskFactor(customer: Customer, weight: Double = 0.75): Double { ... }

The value for weight will default to 0.75 unless the client passes a specific value.

Documentation

If a Function definition includes documentation that conforms to the JSDoc ↗ specification, this documentation will be discovered and published to the Function Registry. This enables users to search for Functions by their descriptions, and can be used to provide further details on what each input parameter means for a Function.

Here is an example of a function with documentation that gets published to the Registry:

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 /** * Computes a similarity score for the two given movies, where 0 represents no similarity * and 1 represents perfect similarity. * * @param movie1 The first movie to compare * @param movie2 The second movie to compare * @param weight The threshold to use for the similarity algorithm */ @Function() public computeSimilarityScore(movie1: Movie, movie2: Movie, weight: Double = 0.75): Double { }