|
| 1 | +# Exporting Generic Swift APIs |
| 2 | + |
| 3 | +Expose generic functions, methods, and callback parameters to JavaScript. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Constrain each type parameter to `BridgedSwiftGenericBridgeable`. JavaScript callers select its concrete Swift type with a token from the generated `BridgeTypes` export. |
| 8 | + |
| 9 | +```swift |
| 10 | +import JavaScriptKit |
| 11 | + |
| 12 | +@JS public final class ValueStore { |
| 13 | + private var values: [String: any BridgedSwiftGenericBridgeable] = [:] |
| 14 | + |
| 15 | + @JS public init() {} |
| 16 | + |
| 17 | + @JS public func put<T: BridgedSwiftGenericBridgeable>(_ key: String, _ value: T) { |
| 18 | + values[key] = value |
| 19 | + } |
| 20 | + |
| 21 | + @JS public func get<T: BridgedSwiftGenericBridgeable>(_ key: String) -> T? { |
| 22 | + values[key] as? T |
| 23 | + } |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +```javascript |
| 28 | +import { BridgeTypes } from "./bridge-js.js"; |
| 29 | + |
| 30 | +const store = new exports.ValueStore(); |
| 31 | +store.put("count", 42, BridgeTypes.Int); |
| 32 | +store.put("title", "Draft", BridgeTypes.String); |
| 33 | +store.get("count", BridgeTypes.Int); // 42 |
| 34 | +store.get("title", BridgeTypes.String); // "Draft" |
| 35 | +store.get("count", BridgeTypes.String); // null: stored as Int |
| 36 | +store.release(); |
| 37 | +``` |
| 38 | + |
| 39 | +Pass one token per generic parameter after the regular arguments, in declaration order. Tokens use Swift names and underscore-separated namespaces, such as `BridgeTypes.API_Building`, even when the type has a separate JavaScript name. Import `BridgeTypes` from the generated module, not the `exports` object. |
| 40 | + |
| 41 | +The token selects the concrete return type, including for return-only generics such as `get`. Generic values may use `T`, `[T]`, `T?`, or `[String: T]`, mixed with concrete parameters and results. See <doc:Supported-Types> for types usable as `T`. |
| 42 | + |
| 43 | +### Async functions and callbacks |
| 44 | + |
| 45 | +Generic exports and their callback parameters may be `async` or `throws(JSException)`. Callbacks can use the same generic types; an `@escaping` callback stays alive until Swift releases it and must run on the same JavaScript runtime/thread. Use `throws(JSException)` for callbacks that throw or reject a promise. |
| 46 | + |
| 47 | +### Protocol constraints |
| 48 | + |
| 49 | +Add `@JS` protocol constraints with `T: BridgedSwiftGenericBridgeable & GraphNode`, or use `T: GraphNode` if `GraphNode` inherits `BridgedSwiftGenericBridgeable` (see <doc:Exporting-Swift-Protocols>). Constraints are preserved in TypeScript; unknown or non-conforming tokens throw `TypeError` before arguments cross the bridge. |
| 50 | + |
| 51 | +Exported generic initializers are unsupported; use an ordinary initializer as above or a generic factory method. Imported generic `@JSClass` initializers remain supported (see <doc:Importing-JS-Function>). See <doc:Unsupported-Features> for other export restrictions. |
0 commit comments