Object combination syntax, but for type records

I was trying to save some lines of code recently by using a type and extending the MonitoringType variant (i.e. from { #a; #b } to { #a; #b; #c };)

public type CanisterConfig = TypesV6.CanisterConfig and {
    monitoringType : MonitoringCanisterType;
};

But I later realized later that this is a type intersection and not an extension or overwrite.

It would be nice to have a syntax similar to the object combination/extension syntax where I can specify inherit an already defined record type, but then overwrite/extend one of the properties. Especially if the property is a variant that’s being added to.

Maybe this syntax could reuse the with keyword?

public type CanisterConfig = { TypesV6.CanisterConfig with
    monitoringType : MonitoringCanisterType;
};
3 Likes

Actually, in this case you can use type level or to combine the variants into a larger variant supertype:

actor {

  type V1 = {#a};
  type V2 = V1 or {#b};  // restricted union
  type V3 = V1 and {#b}; // restricted intersection

  let t1 : [V2] = [#a, #b]; // accepted

  let t2 : [V3] = [#a, #b]; // rejected (v3 is the empty variant `{#}`)

}
2 Likes

@claudio, I think the OP wants to extend a variant inside a record without repeating either. I don’t think that’s expressible with union and intersection, since you’d need a union on the inner level (to extend the variant), but an intersection on the outer (to list just one record field).

The odd thing about this is that it isn’t really a type refinement — the result is not a subtype, instead it’s rather ad-hoc code reuse. I’d be suspicious of introducing extra syntax for such an odd case, doubting that this kind of approach would scale well.

The way cases like this are usually modelled is by parameterising the record over the union it holds. That is, refactor, don’t attempt after-the-fact code reuse that just would “happen to work” if only the language had the “right” feature.

3 Likes

Yep, you’re right. I didn’t read carefully enough.