Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose intersection types? #120

Open
pdesaulniers opened this issue May 21, 2020 · 7 comments
Open

Expose intersection types? #120

pdesaulniers opened this issue May 21, 2020 · 7 comments
Labels
feature request New feature or request

Comments

@pdesaulniers
Copy link
Member

pdesaulniers commented May 21, 2020

Right now, Teal supports intersection types for function overrides inside record definitions.

Are there any plans to expose an & operator for creating new intersection types? I think this could be useful for simulating inheritance:

local Widget = record
    setPos: function(x: number, y: number)
    draw: function()
end

local __TextBox = record
    setText: function(text: string)
end

local type TextBox = Widget & __TextBox

local x: TextBox = {}
x.setPos(1, 2)
x.setText("heyyy")
@hishamhm
Copy link
Member

No plans to do that at this point. This kind of feature interacts with the entire type system in super subtle ways, and as these things are added, they compound (i.e. they add complexity to the features that were there before). I'm still working out the kinks with union types, because I felt that one was inescapable, but for intersection types I'll avoid them for as long as I can — I'd rather add something specific for record/object inheritance instead and not open that Pandora's Box. (See @mascarenhas's comments on #97 to the effect that adding super general constructs as alternatives to OOP end up more complicated than adding OOP itself.)

@hishamhm hishamhm added the feature request New feature or request label May 26, 2020
@Hedwig7s
Copy link

I still feel true intersection would be a nice addition
Being able to mix and match records (or some equivalent) would make the type system a lot more flexible (kinda lua's thing) and be useful for things like mixins for OOP

@Hedwig7s
Copy link

Hedwig7s commented Oct 14, 2024

With next out there's interfaces now, but I do not feel they cut it
If you have shared parameters across records you have to duplicate each parameter (as its own type or entirely) which is repetitive and bloated
Please consider at the minimum record intersection
The rules would be you have record x and y and record z is x & y. Anything in y that exists in x overrides it (stacking bottom to top)
E.g.

local record x
    a: string
    b: string
end
local record y
    b: number
    c: string
end
local type z = x & y
-- aka
local record z 
    a: string
    b: number -- y overrides x
    c: string
end

Almost all type systems with some form of record or struct type allow some form of type intersection it would be incredibly valuable

@hishamhm
Copy link
Member

The rules would be you have record x and y and record z is x & y. Anything in y that exists in x overrides it (stacking bottom to top)

I don't usually critique every feature suggestion, but a quick exception: This would mean that x & y is different from y & x, which goes against the usual definition of intersection. I dislike implicit override rules like this because they are quite error-prone. Also, your suggestion breaks another invariant of intersection definition that z = x & y implies z is x and z is y; per your suggestion that would be not true. Fixing these issues would result in a behavior quite similar to what can be already achieved with interfaces.

For reference, this is how an example like the above looks like with interfaces in Teal '24 — incompatible fields need to be stated explicitly, but compatible fields can be inherited:

local interface IX
   xa: string
   xb: string
   xc: string
end

local interface IY
   ya: string
   yb: string
   yc: string
end

local record X is IX
   b: string
end

local record Y is IY
   b: number
end

local record Z is IX, IY
   b: number
end

--[[
-- this produces a record with these fields,
-- but Z also satisfies `Z is IX` and `Z is IY`.
local record Z
   xa: string
   xb: string
   xc: string
   ya: string
   yb: string
   yc: string
   b: number
end
]]

@Hedwig7s
Copy link

Wait that is essentially record intersection (or rather more like traits)
That isn't documented you may want to document that

@hishamhm
Copy link
Member

Wait that is essentially record intersection (or rather more like traits)

Yes, it is more like traits (and not exactly like record intersection, but it can be used for similar goals)

That isn't documented you may want to document that

oh, you're right! None of the examples in docs/ actually show multiple inheritance of interfaces!

@hishamhm
Copy link
Member

@Hedwig7s thanks for the nudge! 0065786

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants