Skip to content

Commit f087a0a

Browse files
authored
Merge pull request #1200 from finos/don't-use-union-types-in-context-definitions
Don't use union types in context and API definitions
2 parents 5d2ac00 + 640cd9b commit f087a0a

4 files changed

Lines changed: 45 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
99
### Added
1010

1111
* Added clarification that `id` field values SHOULD always be strings to context schema definition (a restriction that can't easily be represented in the generated types). ([#1149](https://github.com/finos/FDC3/pull/1149))
12+
* Added requirement that Standard versions SHOULD avoid the use unions in context and API definitions wherever possible as these can be hard
13+
to replicate and MUST avoid unions of primitive types as these can be impossible to replicate in other languages. ([#120](https://github.com/finos/FDC3/pull/1200))
1214

1315
### Changed
1416

docs/api/spec.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ The FDC3 API specification consists of interfaces. It is expected that each Des
4848

4949
Other interfaces defined in the spec are not critical to define as concrete types. Rather, the Desktop Agent should expect to have objects of the interface shape passed into or out of their library.
5050

51+
### Implementation language
52+
53+
FDC3 and the Desktop Agent API it defines are intended to be independent of particular programming languages and platforms and hence the original definitions, produced in TypeScript, may be translated into other languages. However, this also places limitations on the API definitions as they need to be widely implementable in other languages.
54+
55+
Specifically, the use of ['unions'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of primitive values in API type and metadata objects, or function parameters SHOULD be avoided as they often cannot be replicated in other languages. Unions of more complex types (such as specific [Context](ref/Context) Types) may be used where a suitable interface is available or can be created to allow the required polymorphism in languages other than TypeScript.
56+
5157
### API Access
5258

5359
The FDC3 API can be made available to an application through a number of different methods. In the case of web applications, a Desktop Agent MUST provide the FDC3 API via a global accessible as `window.fdc3`. Implementors MAY additionally make the API available through modules, imports, or other means.

docs/context/spec.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ interface Context {
6262

6363
or in JSON Schema as:
6464

65-
```JSON
65+
```json
6666
{
6767
"$schema": "http://json-schema.org/draft-07/schema#",
6868
"$id": "https://fdc3.finos.org/schemas/next/context/context.schema.json",
@@ -104,6 +104,39 @@ It may be as simple as adding an optional `$version` property to types, but it c
104104

105105
This Standard defines a number of conventions for the fields of context types that all context objects SHOULD adhere to in order to reduce or prevent competing conventions from being established in both standardized types and proprietary types created by app developers.
106106

107+
#### Avoid union types / composition of primitive types
108+
109+
Both Typescript and JSON Schema allow for a type of polymorphism in types and interfaces that is hard to represent in other languages: allowing the type of a variable to be a ['union'](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) of other, unrelated types. E.g.: in TypeScript
110+
111+
```ts
112+
type Example = SomeOtherType | YetAnotherType;
113+
```
114+
115+
Similar constructs are allowed in JSON Schema by [combining or composing schemas](https://json-schema.org/understanding-json-schema/reference/combining) using the `anyOf` or `oneOf` keywords to specify that a value can take the form defined in one-or-more or one-of-several sub-schemas.
116+
117+
```json
118+
"recipients": {
119+
"title": "Email Recipients",
120+
"description": "One or more recipients for the email.",
121+
"oneOf": [
122+
{
123+
"$ref": "contact.schema.json#"
124+
},
125+
{
126+
"$ref": "contactList.schema.json#"
127+
}
128+
]
129+
}
130+
```
131+
132+
However, other languages can be less flexible. In most languages, polymorphism of object types is possible via the implementation and/or extension of an interface (for example all context types are derived from the [Context](ref/Context) schema, which can be modelled as an interface). However, this approach is not possible if one of the types in the union is a primitive, meaning it's not a class and can't be modified to implement an interface, e.g.:
133+
134+
```ts
135+
type Example2 = SomeOtherType | number;
136+
```
137+
138+
Hence, to ensure that FDC3 context objects are implementable in other languages context schemas MUST NOT use `anyOf`/`oneOf` compositions of primitive types in JSON schema (and, hence, unions of primitive types in TypeScript) and SHOULD avoid compositions of Object types unless a concept that can be defined as an interface (such as [Context](ref/Context)) is available.
139+
107140
#### Identifiers
108141

109142
An `id` field with type `object` is defined in the base [fdc3.context](ref/Context) type, from which all other context objects are derived, and SHOULD be used to encapsulate identifiers. Specific context types may define subfields for specific identifiers as needed.

website/docusaurus.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ module.exports={
4949
themes: ['@docusaurus/theme-mermaid'],
5050
"plugins": [],
5151
"themeConfig": {
52+
"prism": {
53+
"additionalLanguages": ["json","csharp"]
54+
},
5255
"algolia": {
5356
"appId": "YW91L9TW76",
5457
"apiKey": "ab431bb4107069ef51780d8947cd8e0a",

0 commit comments

Comments
 (0)