accordproject / concerto

Business schema language and runtime
https://concerto.accordproject.org
Apache License 2.0
104 stars 97 forks source link

Type Utility Functions (e.g. `Partial`,`Omit`) #830

Open mttrbrts opened 4 months ago

mttrbrts commented 4 months ago

Feature Request 🛍️

Extend the language to include type utility functions over declarations.

Use Case

There are several use cases where clients want to use a variant of a declaration, and currently they would need to define a new type and provide an explicit mapping. This can lead to divergence and isolation of types and discourages reuse.

  1. It has been proposed that amendments to agreements could be modelled by declaring a copy of the Agreement model, but with all fields being optional, this would allow the model to capture changed values for fields that had already been declared in the parent agreement. The amendment model could also be extended with new fields. This is similar to the idea of Patch operation in HTTP servers. It's common in distributed systems to want to update a subset of fields by just specifying those fields have changes. Where clients also want strongly typed signatures, they are forced to redeclare Concepts with all properties marked as optional.

Possible Solution

Extend Concerto to include a type utility operator, similar to Partial<T> in TypeScript. The syntax and semantics still need investigation. It's worth noting that in TypeScript, Partial only applies to root properties, we likely want something that applies to the full tree, e.g. https://grrr.tech/posts/2021/typescript-partial/

Context

Detailed Description

dselman commented 4 months ago

This is an interesting requirement. It feels like syntactic sugar for "create a new type with name TOpt, copying all the fields from the existing type T and making them optional." Do you agree? In particular it doesn't seem like there's a runtime relationship between TOpt and T, although there is a semantic relationship.

I.e. T is a subset of TOpt, but TOpt is not a subset of T. This troubles me somewhat because it means folks will pass Ts and TOpts around their application, while the mapping is not bidirectional:

If things like Pick/Omit are also included then the types diverge even further.

mttrbrts commented 4 months ago

create a new type with name TOpt, copying all the fields from the existing type T and making them optional.

I agree.

Having some kind of runtime relationship could be helpful to allow clients to take shortcuts (like patching), when we have more information about the state of entities.