Repository navigation
Feature Request / Proposal: Traits #311
Description
Activity
I think Mixins are relatively similar to traits, however, there are a few disadvantages (at least as it's described in the handbook):
- You have to redeclare class members and methods in the implementing class to satisfy the compiler.
- You have to "apply" the mixins (i.e. copy the class members and methods from the mixin class) using a custom function.
Are the points 1 and 2 by design or are these feature yet to be implemented?
Mixins is an ugly way that feels like we are using ecmascript 3. Traits would allow us to use a more object oriented clean syntax.
Reacted by Staffan Selander, Sajjad Ziaenezhad Shirazi, James O'Cull, Eliya Cohen, Marek Hanzal, Michal Marek, Somefive, Francesco Borzì, Pietro Paolo Vismara, Jacob and 10 moreReacted by Felix Becker, Nicolas Gryman and d-damienThis would certainly be awesome. I don't care how it's done, but this would be great--I use TS mainly in games and engines, and the ability to "mixin" methods from a trait would be great for actors/objects in games (for example, an object importing an EventDispatcher but inheriting from a base class).
class Actor { x: number; y: number; // ... etc } class Player extends Actor { import Traits.Eventing.EventDispatcher; update(engine) { // using my event dispatcher trait this.publish(new Event(...)); } }I don't know how this will work with TS to allow using traits like interfaces (maybe simply traits can implement interfaces).
class SomeClass { public listen(emitter: EventDispatcher) { emitter.on("eventName", this.handleSomeEvent); } handleSomeEvent(args) { ... } } new SomeClass().listen(player);Traits as part of Typescript and its type system would be really helpful to use the DCI programming paradigm with (http://en.wikipedia.org/wiki/Data,_context_and_interaction).
I would prefer a trait solution, where the trait is an interface with a default implementation. Such an interface alone would not generate any JS code on compilation.
Like in Scala, such a trait-interface can now be used in two ways:- The interface can be implemented by a class: The class will get the methods "mixed in" (like in Yassel Avila (@yasselavila) code in the first post) .
The class may need to implement methods which don't have a default implementation - The interface can be added to an object when constructing the instance.
Here is an example:
// Trait-Interface with default implementation interface Customer { isGoldMember: false; public discountFactor(): number { return (this.isGoldMember ? 0.1 : 0); } } // Trait-Interface is implemented class MyGoldCustomer implements Customer { public isGoldMember() { return true; } } // Trait-Interface is used on instantiation class Person { constructor(private name: string) {}; public getName():String { return name; }; // ... } var p = new Person('John') with Customer; // p is of type Person AND Customer. The new object gets the methods "mixed in". // The type of p is the same type as class X, if X is defined as "class X extends Person implements Customer"The "with" syntax is borrowed from Scala. Of course some other syntax could be used for mixing trait interfaces into a new instance, e.g.:
new Person('John') & Customer;
This syntax would fit to union typers (#805). With traits we have another sort of union type, but the instance is implementing both types, not one of them.I'm curious if this suggestion is compatible with the current Typescript type system. Any thoughts?
Reacted by Cosmin Valentin Sontu- The interface can be implemented by a class: The class will get the methods "mixed in" (like in Yassel Avila (@yasselavila) code in the first post) .
anatoliyarkhipov commented
on Nov 1, 2014 More actionsAlso, without multiple inheritance or traits, not possible to use TypeScript with Dojo Toolkit. The whole library is built on mixins system. Of course, we can use default "dojo/_base/declare", but this way negates the benefits from classes and interfaces in TypeScript.
TypeScript team, are you guys open to receiving possible implementations of this feature?
Reacted by Andrei Markeev, Rodolfo Nogueira and LinboLenWe'd be open to implementations in the future but it's important that we first nail down a proposal we can all agree on. It'd be getting ahead of ourselves to start reviewing an implementation before we nail down what is and isn't the intended behavior here.
No problem. SitePen is currently working on defining some package specifications for Dojo and this is one of the areas that we are looking to improve, so once we get a bit further along and actually begin the work of defining technical proposals those will be brought here. A prototype implementation would be useful to inform that decision-making and may form a suitable foundation for a final implementation, but these are early days, we have no code yet. I just didn’t want to have anyone on this side start going down the road and then find out that there is no chance to accept this, or that after talking to Mohamed Hegazy (@mhegazy) about C3 linearization that you guys wanted to move in that direction instead.
Jon (@jbondc) Great! Looking over what you are proposing so far I would probably start by just focusing on the compiler side of things and not even thinking about any runtime enhancements in order to keep the initial feature very clear and focused (like the OP).
I understand not wanting to introduce new reserved words that weren’t future reserved words in the EcmaScript spec but
import classis very unfortunate. The strawman introduced a “trait” adjective for class (trait class), which is better.I/others will have additional feedback over the coming months on this.
Jon (@jbondc), there is a similar proposal on the old codeplex site. What do you think about it?
Just a brief update for everyone watching: I should have a complete(ish) proposal to share in the next couple of days at the latest. Sorry for the delay.
Our proposal is now available at https://docs.google.com/a/sitepen.com/document/d/112Xw-t8eh-eFIdKhn7LeDbGhO86XwlKv-Fwc6j9U-Oc/edit for discussion. (Please let me know if you prefer this to be in another format/location.) This proposal focuses purely on enhancing the compiler and doesn’t include any runtime enhancements.
Looking forward to your feedback and working with the rest of the team and community on refining these proposals into something that will be accepted into TypeScript.
Colin Snover (@csnover) +1... but ... what about use only 'trait' instead of 'traitclass'?
9 remaining items
anatoliyarkhipov commented
on Apr 10, 2015 More actionsAs long as the composing class implements all conflicting methods, there is no conflict reported by the compiler:
To be able to do this, programmer must know about all methods in all imported mixins and which of them are in conflict. Why he should if it is possible resolve this automatically like
dojo/declaredoes (like indstoreexample by Colin Snover (@csnover))?- addedDeclinedThe issue was declined as something which matches the TypeScript visionThe issue was declined as something which matches the TypeScript visionand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Apr 27, 2015 RyanCavanaugh commented
on Apr 28, 2015 MemberMore actionsThere's a lot of overlap here with mix-ins; it would be bad (or at least treacherous) to do both. With mix-ins being a potential part of ES7/ES8+, we want to take the runtime side of this very conservatively and get TC39 to agree on a proposal in this area first.
Features specific to the type system to support these patterns are still on the table, but we'll track those in other issues.
Reacted by Lasana MurrayIs there an update on how/if mixins will become a first class capability of typescript rather than a bit of a hack with separated registration as it currently stands?
Is there an update on how/if mixins will become a first class capability of typescript rather than a bit of a hack with separated registration as it currently stands?
I am sure I will be corrected if I am wrong, but the TypeScript team have made it clear that because this is a domain that TC39 has indicated they will address, the team feel that this is something it doesn't feel it can introduce as it would likely cause incompatibilities with ES in the future.
The implications are, those of us who are passionate about it should be championing it within TC39. The concepts of mixins/traits were part of the originally Harmony proposals, but didn't make it into the spec. Also, as far as I am aware, there isn't any active advocacy on this specific area in TC39 at the moment. Once there is a proposal sufficiently through the process in TC39, then I believe the TypeScript team would be more than glad to implement it.
Kitson Kelly (@kitsonk) thanks for the update, I guess we just have to hope for TC39, I'll see if I can find any discussion on the matter. I feel at this point that traits are the only major capability missing - I'm currently managing a site with ~50k sloc TS, and the mixin registrations are somewhat unwieldy.
+1 for this feature
What's the status on this feature?
What's the status on this feature?
See https://blogs.msdn.microsoft.com/typescript/2017/02/02/announcing-typescript-2-2-rc/ ... basically they're not adding new language grammar, but by making some changes to the way Classes work, it's possible/easier to achieve now.
One powerful pattern that is possible with traits is this (similar to what Johannes Bergmann (@jbman) mentioned):
trait AccountService { debit: (account: Account, amount: number) => Account; credit: (account: Account, amount: number) => Account; transfer(from: Account, to: Account, amount: number): [Account, Account, number] { return [this.debit(from, amount), this.credit(to, amount), amount] } }
This is not something that TC39 can help us with as in this particular form it's only relevant to statically typed languages. It can be done with
abstractclasses but then we lose the benefit of the mixin pattern as we move the problem into the inheritance area. Trait composition also makes pattern such as "cake" pattern possible.Reacted by ackim williams, Somefive and Richard Simpson+1
You can have a look at a simple library i wrote at TypeScript Mix I think it fits nicely into how you would want to use traits/mixins
Reacted by Romain Deneau and Zia Saidi- locked and limited conversation to collaborators
on Jun 18, 2018
ORIGINALLY PROPOSED IN http://typescript.codeplex.com/workitem/838
Traits, as "compile-time" partial classes, would perfectly fit with TS ideology and resolve problems of multiple inheritance/mixins.
Traits in Scala: http://en.wikibooks.org/wiki/Scala/Traits
Traits in PHP: http://php.net/trait
I propose minimal traits similar to PHP implementation.
The code above could be compiled to JS below (can be optimized, just showing the main idea):
Unresolved name conflicts should raise a compile time error.
I think it would be a great advance for the language. But the proposal has more than one year made (in codeplex) and has not yet been implemented.