Types reference

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. Below is the full list of currently supported function registry types and their corresponding language types.

Function registry typeTypeScript v1 typeTypeScript v2 typePython type
AttachmentAttachmentAttachmentAttachmentExample
BooleanbooleanbooleanboolExample
BinaryNot supportedNot supportedbytesExample
ByteNot supportedNot supportedint*Example
DateLocalDateDateISOStringdatetime.dateExample
DecimalNot supportedNot supporteddecimal.DecimalExample
DoubleDoubleDoublefloat*Example
FloatFloatFloatfloatExample
GroupGroupNot supportedNot supportedExample
IntegerIntegerIntegerintExample
ListT[] or Array<T>T[] or Array<T>list[T]Example
LongLongLongint*Example
MapFunctionsMap<K, V>Record<K, V>dict[K, V]Example
Media referenceMediaItemNot supportedNot supportedExample
NotificationNotificationNot supportedNot supportedExample
ObjectMyObjectTypeOsdk.Instance<MyObjectType>MyObjectTypeExample
Object setObjectSet<MyObjectType>ObjectSet<MyObjectType>MyObjectTypeObjectSetExample
Ontology editvoidEditsOntologyEditExample
OptionalT | undefinedT | undefinedtyping.Optional or T | NoneExample
PrincipalPrincipalNot supportedNot supportedExample
RangeIRange<T>Range<T>Range[T]Example
SetSet<T>Not supportedset[T]Example
ShortNot supportedNot supportedint*Example
StringstringstringstrExample
Struct/custom typeinterfaceinterfacedataclasses.dataclassExample
TimestampTimestampTimestampISOStringdatetime.datetimeExample
Two-dimensional aggregationTwoDimensionalAggregation<K, V>TwoDimensionalAggregation<K, V>TwoDimensionalAggregation[K, V]Example
Three-dimensional aggregationThreeDimensionalAggregation<K, S, V>ThreeDimensionalAggregation<K, S, V>ThreeDimensionalAggregation[K, S, V]Example
UserUserNot supportedNot supportedExample

Although both Integer and Long correspond to the Python type int, any fields marked as int directly in your function signature will be registered with type Integer. Therefore, we instead recommend using either the Integer or Long types from the API to register numerical data types. Similar guidelines apply to Float and Double; if the Python type float is directly in your function signature, it will be registered as Float by default.

Scalar types

Scalar types represent a single value and are commonly used to hold textual, numeric, or temporal data.

In JavaScript and TypeScript, there is one number type that is commonly used to represent both integer and floating-point values. In order to provide further type validation and structure, we only support the numeric aliases exported from the @foundry/functions-api package for TypeScript v1 functions and the @osdk/functions package for TypeScript v2 functions. Similarly, when working with numeric types in Python functions we recommend using the type aliases exported from the functions.api module.

Boolean

Copied!
1 2 3 4 5 6 7 8 import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public isEven(num: Integer): boolean { return num % 2 === 0; } }

String

Copied!
1 2 3 4 5 6 7 8 import { Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public greet(name: string): string { return `Hello, ${name}!`; } }

Short

Represents integer values from -32,768 to 32,767.

In Python functions, the Short type is an alias for the built-in int type.

Copied!
1 2 3 4 5 from functions.api import function, Short @function def increment(num: Short) -> Short: return num + 1

Integer

Represents integer values from (-231) to (231 - 1).

  • In both TypeScript v1 and v2 functions, the Integer type is an alias for the built-in number type.
  • In Python functions, the Integer type is an alias for the built-in int type.
Copied!
1 2 3 4 5 6 7 8 import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public sum(a: Integer, b: Integer): Integer { return a + b; } }

Long

Represents integer values from -(253 - 1) to (253 - 1). These bounds are equivalent to Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER in JavaScript to prevent precision loss when functions are called from browser contexts.

  • In TypeScript v1 functions, the Long type is an alias for the built-in number type. In TypeScript v2 functions, the Long type is an alias for the built-in string type.
  • In Python functions, the Long type is an alias for the built-in int type.
Copied!
1 2 3 4 5 6 7 8 import { Function, Long } from "@foundry/functions-api"; export class MyFunctions { @Function() public subtract(a: Long, b: Long): string { return (BigInt(a) - BigInt(b)).toString(); } }

Float

Represents a 32-bit floating-point number.

  • In both TypeScript v1 and v2 functions, the Float type is an alias for the built-in number type.
  • In Python functions, the Float type is an alias for the built-in float type.
Copied!
1 2 3 4 5 6 7 8 import { Float, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public multiply(a: Float, b: Float): Float { return a * b; } }

Double

Represents a 64-bit floating-point number.

  • In both TypeScript v1 and v2 functions, the Double type is an alias for the built-in number type.
  • In Python functions, the Double type is an alias for the built-in float type.
Copied!
1 2 3 4 5 6 7 8 import { Double, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public divide(a: Double, b: Double): Double { return a / b; } }

Decimal

Copied!
1 2 3 4 5 6 from decimal import Decimal from functions.api import function @function def return_pi() -> Decimal: return Decimal('3.1415926535')

Date

Represents a calendar date.

Copied!
1 2 3 4 5 6 7 8 import { Function, LocalDate } from "@foundry/functions-api"; export class MyFunctions { @Function() public returnDate(): LocalDate { return LocalDate.fromISOString("1999-10-17"); } }

Timestamp

Represents an instant in time.

Copied!
1 2 3 4 5 6 7 8 import { Function, Timestamp } from "@foundry/functions-api"; export class MyFunctions { @Function() public getCurrentTimestamp(): Timestamp { return Timestamp.now(); } }

Binary

In Python functions, the Binary type is an alias for the built-in bytes type.

Copied!
1 2 3 4 5 from functions.api import function @function def encode_utf8(param: str) -> bytes: return param.encode('utf-8')

Byte

In Python functions, the Byte type is an alias for the built-in int type.

Copied!
1 2 3 4 5 6 7 from functions.api import function, Byte @function def get_first_byte(param: str) -> Byte: if len(param) == 0: raise Exception("String length cannot be zero.") return param.encode('utf-8')[0]

Collection types

Collection types are parameterized by other types. For example, Array[String] is a list of strings and Map[String, Integer] is a dictionary with string keys and integer values. The parameterized types must be specified, and the type must be another supported type. Map keys can only be scalar types or an Ontology object type.

List

Copied!
1 2 3 4 5 6 7 8 import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public filterForEvenIntegers(nums: Integer[]): Integer[] { return nums.filter(num => num % 2 === 0); } }

Map

Maps are commonly used to key by a scalar type and access an associated value that can be of any other function registry type.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 import { Function, FunctionsMap } from "@foundry/functions-api"; export class MyFunctions { @Function() public getMap(): FunctionsMap<string, string> { const myMap = new FunctionsMap<string, string>(); myMap.set("Name", "Phil"); myMap.set("Favorite Color", "Blue"); return myMap; } }

Additionally, maps support Ontology objects as keys.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { Function, FunctionsMap } from "@foundry/functions-api"; import { Airplane } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getObjectMap(aircraft: Airplane[]): FunctionsMap<Airplane, Integer | undefined> { const myMap = new FunctionsMap<Airplane, Integer | undefined>(); aircraft.forEach(obj => { myMap.set(obj, obj.capacity); }); return myMap; } }

Set

Copied!
1 2 3 4 5 6 7 8 import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public getSizeOfSet(mySet: Set<Integer>): Integer { return mySet.size; } }

Optional

  • In TypeScript functions, optional parameters are declared as varName?: T or varName: T | undefined. For example, a function that has an optional integer parameter named value could be declared as either value?: Integer or value: Integer | undefined. TypeScript functions can also declare an optional return type by specifying a type of T | undefined. For example, a function that may return either an Integer or no value would have a return type of Integer | undefined.
  • In Python functions, optional parameters and return values can be declared using typing.Optional[T] or T | None. The T | None syntax requires Python 3.10 or greater.
  • In both TypeScript and Python functions, the parameterized type T must be specified, and it must be another supported type.
Copied!
1 2 3 4 5 6 7 8 9 10 11 import { Function } from "@foundry/functions-api"; export class MyFunction { @Function() public greet(name?: string): string | undefined { if (name === undefined) { return undefined; } return `Hello, ${name}!`; } }

Functions also support default values in the function signature.

Copied!
1 2 3 4 5 6 7 8 9 import { Double, Function } from "@foundry/functions-api"; import { Customer } from "@foundry/ontology-api"; export class MyFunctions { @Function() public computeRiskFactor(customer: Customer, weight: Double = 0.75): Double { // ... } }

Struct/custom type

Custom types are composed of other supported types (including other custom types) and can be used in function signatures.

  • In TypeScript functions, custom types are user-defined TypeScript interfaces using the interface keyword.

    • Optional fields are supported through either the ? optional token or a union with undefined.
  • In Python functions, custom types are user-defined Python classes.

    • To be a valid custom type, the class must adhere to the following:
      • The class must have type annotations on all of its fields.
      • The field types must be supported types; either the primitive API types or native Python types (as defined in the table above) may be used.
      • The __init__ method must accept only named arguments with the same names and type annotations as the fields.
    • The dataclasses.dataclass decorator can be used to automatically generate an __init__ method that conforms with these requirements.
Copied!
1 2 3 4 5 6 7 8 9 10 11 12 import { Function, Integer } from "@foundry/functions-api"; import { Passenger } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getPassengerInfo(passenger: Passenger): PassengerInfo { return { name: passenger.name, age: passenger.age, }; } }

Aggregation types

Aggregation types can be returned from functions for use in other parts of the platform, such as Charts in Workshop.

There are two supported aggregation types:

  • A two-dimensional aggregation maps from a single bucket key to a numeric value. For example, this could be used to represent an aggregation such as a count of employees with a specific job title.
  • A three-dimensional aggregation maps from two bucket keys 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.

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.
  • Range 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 Date and Timestamp, represent bucketed aggregations on date ranges.

Range

Copied!
1 2 3 4 5 6 7 8 9 10 11 import { Function, Integer, IRange } from "@foundry/functions-api"; export class MyFunctions { @Function() public getRange(min: Integer, max: Integer): IRange<Integer> { return { min, max, }; } }

Two-dimensional aggregation

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 import { Double, Function, TwoDimensionalAggregation } from "@foundry/functions-api"; export class MyFunctions { @Function() public myTwoDimensionalAggregation(): TwoDimensionalAggregation<string, Double> { return { buckets: [ { key: "bucket1", value: 5.0 }, { key: "bucket2", value: 6.0 }, ], }; } }

Three-dimensional aggregation

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 25 import { Double, Function, ThreeDimensionalAggregation } from "@foundry/functions-api"; export class MyFunctions { @Function() public myThreeDimensionalAggregation(): ThreeDimensionalAggregation<string, string, Double> { return { buckets: [ { key: "group-by-1", groups: [ { key: "partition-by-1", value: 5.0 }, { key: "partition-by-2", value: 6.0 }, ], }, { key: "group-by-2", groups: [ { key: "partition-by-1", value: 7.0 }, { key: "partition-by-2", value: 8.0 }, ], }, ] }; } }

Ontology types

Ontology imports

Object types must be imported into your repository to use them in function signatures. Learn more about Ontology imports.

Object

Object types from your ontology can be used as both inputs and outputs in your function signature. To either accept or return a single instance of an object type, import the object type from your Ontology SDK and use that type to annotate your function.

Copied!
1 2 3 4 5 6 7 8 9 import { Function, Integer } from "@foundry/functions-api"; import { Airplane } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getCapacity(airplane: Airplane): Integer { return airplane.capacity; } }

Object set

There are two ways to pass a collection of objects into and out of a function: concrete collections of objects (such as arrays), or object sets.

Passing an array of objects to a function enables executing logic over a concrete list of objects at the expense of loading the objects into the function execution environment up front. An object set, however, allows you to perform filtering, search-around, and aggregation operations and only load the final result when you request it.

We recommend using an object set instead of an array because an object set often achieves better performance and allows more than 10,000 objects to be passed into the function.

The below example shows how to filter an object set without loading the objects into memory, allowing you to return the filtered object set to a different part of the application.

Copied!
1 2 3 4 5 6 7 8 9 import { Function } from "@foundry/functions-api"; import { Airplane, ObjectSet } from "@foundry/ontology-api"; export class MyFunctions { @Function() public filterAircraft(aircraft: ObjectSet<Airplane>): ObjectSet<Airplane> { return aircraft.filter(a => a.capacity.range().gt(200)); } }

Ontology edit

In addition to writing functions that read data from the Ontology, you can also write functions that create objects and edit the properties and links between objects. For more details about how edit functions work, refer to the overview page.

To be registered as edit functions, TypeScript v1 functions require a void return type in the signature. TypeScript v2 and Python functions, however, require explicitly returning a list of Ontology edits.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { Edits, OntologyEditFunction } from "@foundry/functions-api"; import { Employee, LaptopRequest, Objects } from "@foundry/ontology-api"; export class MyFunctions { @Edits(Employee, LaptopRequest) @OntologyEditFunction() public assignEmployee(newEmployee: Employee, leadEmployee: Employee): void { const newLaptopRequest = Objects.create().laptopRequest(Date.now().toString()); newLaptopRequest.employeeName = newEmployee.name; newEmployee.lead.set(leadEmployee); } }

Attachment

Copied!
1 2 3 4 5 6 7 8 import { Attachment, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public loadAttachmentContents(attachment: Attachment): Promise<string> { return attachment.readAsync().then(blob => blob.text()); } }

Notification

Notification types can be returned from a function 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, review our guide.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import { EmailNotificationContent, Function, Notification, ShortNotification, } from "@foundry/functions-api"; export class MyFunctions { @Function() public buildNotification(): Notification { return Notification.builder() .shortNotification(ShortNotification.builder() .heading("Issue reminder") .content("Investigate this issue.") .build()) .emailNotificationContent(EmailNotificationContent.builder() .subject("New issue") .body("hello") .build()) .build(); } }

Media types

Media references

Functions can accept and return media items. For more information, review the guide on media.

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import { Function, MediaItem } from "@foundry/functions-api"; export class MyFunctions { @Function() public transcribeAudioFile(file: MediaItem): Promise<string | undefined> { if (MediaItem.isAudio(file.mediaReference)) { return await file.mediaReference.transcribeAsync({ language: TranscriptionLanguage.ENGLISH, performanceMode: TranscriptionPerformanceMode.MORE_ECONOMICAL, outputFormat: {type: "plainTextNoSegmentData", addTimestamps: true} }); } return undefined; } }

Users, groups, and principals

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.

User

Copied!
1 2 3 4 5 6 7 8 import { Function, User } from "@foundry/functions-api"; export class MyFunctions { @Function() public getUserEmail(user: User): string { return user.email; } }

Group

Copied!
1 2 3 4 5 6 7 8 import { Function, Group } from "@foundry/functions-api"; export class MyFunctions { @Function() public getGroupName(group: Group): string { return group.name; } }

Principal

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import { Function, Principal } from "@foundry/functions-api"; export class MyFunctions { @Function() public getPrincipalType(principal: Principal): string { switch (principal.type) { case "user": return "User"; case "group": return "Group"; default: return "Unknown"; } } }