-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Partial classes #563
Comments
I think you employ "partial" on modules too and help resolve this issue raised here. |
@disshishkov perhaps extension methods be sufficient : #9 |
What kind of situations do you want to use this for, and how do existing solutions fall short of that? Note that this was implemented in C# to support WinForms-type editing scenarios where you have an auto-generated file and a user-edited file contributing to the same type; I'm not sure those kind of situations apply in JavaScript/TypeScript. |
Some classes can has many line numbers, just for better read splitting to several separate classes will help. You can split by different type, for example by logic (in case where this logic can not moved to another class), by visibility (private and public) and other. In case when combing of partial classes can has problems (for example 2 partial classes same the same method/variable declaration) compiler should notify and throw error. |
This isn't really compelling. If your class is so large it can't be comfortably edited in a single file due to its sheer size, it's a very major design smell (e.g. comments in http://programmers.stackexchange.com/questions/157482). Splitting by different type/logic/visibility/etc is something that could be handled by an IDE or by organization within a single file. It's worth discussing why your classes are so big they can't be navigated (is it because the navigation tools should be better?), and if there are better ways the language could support decomposing a class rather than just splitting it. |
Personally, I think "partial classes" should exist, but behave like modules that merge together. I have a system with modules that, although intellisense sees all modules (as it should), the actual JS containing it is only loaded when needed. I think that same would be great for classes as well - to only load the parts needed. I've also wanted to create a function, and use a class to further expand on it. Currently, you can only do this with modules. |
A use case for partial classes is for generated proxy classes. E.g. WebAPI or SignalR wrappers. It would be really nice to be able to extend the generated proxy classes with custom logic. Especially when generating classes for models it would be nice to be able to attach business logic directly to the model classes returned from the api. |
+1 kvantetore. The use case is exactly the same as .net; a portion of the class is generated (in our case, from Avro schemas) and you want to add additional helper code for working with the generated classes. |
I like this suggestion. I would like to have partial classes in order to separate attributes/properties of classes forming my "data hierarchy" which could be gathered in one single file, from their methods which can be split in several other files. It would make code clearer and easier to understand in one glance imo. My data hierarchy file: class A {
x: number;
y: number;
z: number;
}
class B extends A {
value: string;
flag1: boolean;
flag2: boolean;
} File containing methods of class A: class A {
constructor(x: number, y: number, z: number) {
this.x = x;
this.y = y;
this.z = z;
}
method1(...) { ... }
...
methodN(...) { ... }
} File containing methods of class B: class B extends A {
constructor(x: number, y: number, z: number, value: string) {
super(x, y, z);
this.value = value;
this.flag1 = false;
this.flag2 = false;
}
method1(...) { ... }
...
methodN(...) { ... }
} |
+1 from me. I would like to use tt templates to generate Typescript classes, but add to them in a separate file that won't get replaced by the template generation. |
+1 This will really help me with my auto generated classes that I need to extend |
Partial Class is really nice but it doesn't make sense to have it. It showed you have a design problem. Rule of thumb in programming is to keep it simple stupid (KISS), regardless of languages you use, is to break apart large class into smaller ones - by either 1) splitting off scripts into classes and call them (Other classes can also call that smaller classes too instead of re-inventing the wheel), or 2) break apart & convert into Abstract/Interface/Inheritance/Virtual etc. or polymorphism. Let's say you have a Vehicle with everything in it. A partial class doesn't make sense and it introduce complexity & overhead here where it makes more sense to do this instead. Create an Engine class, Tranny class, Drivetrain class, Door class & Tire class as seperate classes and move scripts over to them, that when called can still define a Vehicle within the Vehicle class. It reduce lengthy scripts & script complexity. Chance are you will find you have Door scripts here and there which can be simplified by a Door class. Interface/Abstract/Inheritance/Virtual can be use to alter the Door class definition on some scripts in the Vehicle class. You're also more likely to have less develoment time this way. I once had the ASP.NET C# Blog that use lots of partial classes. I had struggled with it cuz of too many partial classes and you don't know where they are. It is sort of like dealing with GOTO logic in programming. Bad bad!! I was never able to create a patch for the bugfix successfully, nor was I able to customize the script cuz it was too buried in pile of partial classes (so do some renamed wording). Just saying it as a 1 cent thought from my mind. |
@fletchsod-developer: Some situations are properly handled by inheritance, but not all. And some developers may misuse partial classes, but not all. There are some situations where I find partial classes very, very useful, but if you don't like them, you don't have to use them. |
@NoelAbrahams, would you be able to acces the definitions from file1 in file but not vice versa? That's ok for me as long as is independent of inclusion order. |
I really hope you guys consider partial classes a la C# for TS... for me the only reason is code generation, which is the primary reason behind C#'s partial classes... we are currently doing a lot of TS code generation, and we expect to be doing more and more... currently we have to rely on "//<code" regions in order to preserve our custom code... it's OK i guess but it's not a universal solution to extending code generated classes... but partial classes are... this way tools can all use the same way of providing extension points to code generated classes... please do expect C#/VB to TS code generation to be a common thing just because it's common to use TS for the client and C#/VB for the server, and it's common, whether good or bad, to want to share code between server and client, at least structure... partial classes would help extend generated code... C# examples all over the place, not just winforms, also EF, RIA, etc... |
+1 - Could really use this for adding functionality to auto-generated classes; no other elegant solution exists that I can think of or have read about to date... |
+1 - Code generated classes. C#/Java objects serialized to client |
Need this also for merging of generated classes! |
This would be a very useful feature to allow simple merging of generated code with non-generated code. |
+1 |
+1 - We also need it for partially generated classes, would be more elegant than inheritance which emits quite a bit of code that's not needed for this purpose. |
+1 |
Ran into this limitation again - please add this feature! 👍 |
+1 |
2 similar comments
+1 |
+1 |
So back to the point... So instead of pointing out a language feature, what problem are you trying to address with your example? Because the workaround in TypeScript is easy: class Point {
readonly x: number;
readonly y: number;
translate(dx: number, dy: number): Point {
return new Point(this.x + dx, this.y + dy);
}
} |
(and if we are completist, but again, it solves a use, not all use cases) interface PointBase {
x: number;
y: number;
}
interface Constructor<T> {
new (...args: any[]): T;
prototype: T;
}
interface TranslatePointPartial {
translate(dx: number, dy: number): TranslatePointPartial;
}
function TranslatePointPartial<B extends Constructor<PointBase>>(base: B): B & Constructor<TranslatePointPartial> {
return class TranslatePointPartial extends base {
translate(dx: number, dy: number): TranslatePointPartial & PointBase {
return new TranslatePointPartial(this.x + dx, this.y + dy);
}
};
}
class Point {
readonly x: number;
readonly y: number;
}
const MyPoint = TranslatePointPartial(Point);
const instance = new MyPoint();
instance.x;
instance.y;
instance.translate(1, 2); |
I don't see a way to disentangle the two at this point. One could, in theory, write some language ala CoffeeScript that syntactically transformed to TypeScript and use that higher-level language to add new syntactic features while still using TS's type system, but that'd only get you so far. Just picking one of the many other greenfield compile-to-JS languages instead seems like a better choice if that's the goal.
Namespaces aren't going anywhere, for sure. They're just a naming of a pattern that's already in widespread use and they still make plenty of sense in a world of ES6 modules. Modules are just increasingly the way people organize their code and they have a lot of great side benefits. I'm just saying that partial classes make almost no sense in that world, and it'd be odd to add a fundamentally new organizational pattern that's incompatible with it. If the world were moving in the opposite direction and everyone was like "Global scripts with side effects on load are awesome, everyone party on each others' |
Perhaps so... Perhaps they don't make as much sense... But like I have said numerous times, I think even in this thread, partial classes are all about making code generation easier... That's the main benefit I see from them worth the feature in TS... I, and I have to assume many others but that's just a guess, am currently generating tons of TS code from my C# code... But then the question becomes how to safely extend the generated TS code??? This is a far easier question to answer with partial classes... Currently we are resorting to hacks in order to keep custom code in our generated TS code files... Thanks |
Same thing here, we generate the typescript "proxy" for our C# APIs, and we'd like to be able to extend these objects in typescript easily. I'm not a JS specialist so i must be missing something, because, i don't see why being able to split the declaration of classes in multiple TS files (with only one class declaration in only one JS file after compilation) would be a problem for the JS world. As far as i see it, it's transparent for JS, as if it would have been written in one file from the begining. I mean, if you use partial classes or not, the JS output will be exactly the same, but it will prevent the cost of JS object extensibility for our developpers. |
One other thing I wanted to mention that me personally I am not asking the TS compiler to somehow solve the packaging dilemma that might arise when creating an ES6 module using partial classes in different TS files... It makes perfect sense to me at least to compile multiple TS files into a single js file for the ES6 module... Again, partial classes helps code generation significantly... They allow tooling to create large parts of your model with reliable extensibility... |
No, I'm not asking for a new feature anymore. It has been stated over and over that the language can accomplish what I want. I've provided examples of what I want (in C#), but I have yet to see in the helpful examples a way to get to where I need to be at.
Ryan seems to be a moderator here and is closing the issue. That's why. If he is a language authority, then perhaps he shouldn't close the issue before making an effort to understand my need and dismissing this request without providing example of how to do it with native language features. I've stated that I'd like a compile-time solution. And I'm a pretty good developer and have been around for a while programming in many different and obscure languages, and I still have a really hard time with the mixin syntax. I don't get how something that complex and hard to understand got into the language, and yet everyone is rejecting the elegance of partial class syntax, simply, it seems, because it's borrowed from C#. |
🤔 |
@RyanCavanaugh, I know you've made an effort to help. And at this point I'm moving on to try mixins. Or just inheritance, or maybe I'm in such a hurry to get this project done that I'm overlooking a way to do this with generics. Hmm...
And that works fine for me. It's not as pretty and forces my code generated classes to have names that I don't want to use in code. But, again it works. |
At the moment I feel that guys, who are strongly against partial classes, simply misuderstand the concept of partial classes, and they think that partial classes are something what partial classes are not. To make it clear: partial class is a syntactical construction, which lets you split the definition of a same single class into several physical files. Keywords here are "same" and "single". TypeScript's documentation gives bad definition of partial classes (first paragraph here: https://www.typescriptlang.org/docs/handbook/mixins.html). Example of real partial classes concept: File "Point.generated.ts":
File "Point.codeByHand.ts":
They compile into "Point.js" - and the name comes from the name of a class, not from the names of files:
Mixins, when used as "partial classes" (and I strongly believe that this term in documentation is misused) actually represent a multiple inheritance (https://en.wikipedia.org/wiki/Multiple_inheritance). So, as we see, we discuss two different tools: real partial classes and multiple inheritance. These are two different tools. And as any tool - they have their own area of application. In other words: a carpenter may use a hammer instead of a mallet, when the mallet is not available, but the hammer is not the right tool. IMHO, this discussion has no future and we should stop it. While I still see no technological problems for real partial classes, the team really has no wish to implement them, at least for now. |
The TS team does not want to implement TS-specific features if possible. If you do want to discuss more then here is a better place: https://esdiscuss.org/topic/class-syntax-enhancements I hope there is a GitHub repo on TC39 side to discuss this things rather than mailing based one :/ |
I don't think anyone here is misunderstanding the definition of partial classes, I think you're perhaps misunderstanding the definition of classes in JavaScript. If you are under the impression that JavaScript classes are at all like the classes found in virtually any other widely used language, then it might well appear to you that others others are misunderstanding. However, as has been said multiple times in this discussion, I know I've said it explicitly at least once, JavaScript classes are not declarative constructs they are imperative. They do not exist until statements are executed. Defining them relies on mutation. This already makes them brittle and order dependent when it comes to inheritance. This could go on and on...
I really don't think that is correct. Everyone loves C#, even Java programmers 😛, and TypeScript is not different for the sake of being different. |
For citated and below: I am talking about the TypeScript. |
The problem with this satatement there is no such thing as a TypeScript class. |
Oh, boy! Some people will use anything as a reason. |
I mean that they are JavaScript classes. While I am at times guilty of being pedantic, I'm very specifically making this distinction because we need to agree on the definition of the term class before we can discuss what features are simple to add to them. I think we don't mean the same thing when we speak of classes and that causes cognitive dissonance and impedes mutual understanding. |
|
In fact the first post in this topic perfectly describes what was requested, therefore this discussion has no future :) |
@greendimka yes, it has no future as it seems TypeScript will never have partial classes. In my view, that is a good thing. However, misunderstandings and miscommunications are not good things which is why I am still conversating with you. Unfortunately, you do not seem to be interested in either A. Explaining what JavaScript are classes are that one might might change their mind and come to agree with you that they can trivially be made partializable. B. Learning from others about what JavaScript classes are so that you must understand the opposing point of view. I think that this is a shame, but I will not discuss it further if you so wish. |
I am not against any discussions. But it has been stated several times here that partial classes will not be implemented (at least not now). So I think it is better to concentrate on other things. Maybe TypeScript can be changed in the future, who knows. |
@aluanhaddad All we want out of partial classes is the syntactic sugar that enables us to amalgamate all the various definitions of a single TypeScript class into one final - low level - 3GL - Javascript class definition. There should be no impact on the final JavaScript class definition, right? Why is the final product of the transpilation to Javascript even part of this discussion? Seriously. |
@cosmoKenney "its just ES.next with types" is a big selling point that converts JavaScript developers. If you want something more, you're looking at the wrong language. Maybe try Scala.js instead? edit: I just had an interesting realisation that in ES.next partial classes can be implemented with a custom module loader. If you use import {MyClass} from './myclass.*' the loader could merge all exported MyClass definitions from any files matching the wildcard into a single class, then provide that. |
@spion I like how you are quite correctly referring to them as ES.next partial classes. An ES module loader, such as a browser, or loader polyfill, such as SystemJS, would then support partial classes. I definitely agree with you regarding Scala.js
Mixins as seen in TypeScript are an ECMAScript design pattern that TypeScript types. Generics are a type system feature so they do not apply. Modules are an ECMAScript feature. Namespaces are a syntactic sugar for and a formalization of an ECMAScript design pattern. Type Casting does not exist in TypeScript. |
@aluanhaddad why do you keep making this out as a run-time thing? Module loaders and all that have nothing to do with transpiling. |
+1 |
That is not correct. Look at the SystemJS and Webpack ecosystems and you will see otherwise. Even more traditional, and rock solid gulp workflows rely on the correspondence between input and output files. |
+1 I need partial class because we are generating most of the base class using tools (to automate when there's a changes in the model). We then use partial class to add functionality to the class in a separate files so it won't be overwrite by the tool (that auto-generate the class). |
Add support of partial classes. Mixins is not the same, because it's run-time realization. Need compile realization, where partial classes will be combine into one before converting typescript to javascript.
will be:
The text was updated successfully, but these errors were encountered: