Typescript: Partial classes

Created on 29 Aug 2014  ·  224Comments  ·  Source: microsoft/TypeScript

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.

//FileA.ts
partial class ClassA
{      
    constructor(public name: string) {}
    public sayHello(): string { return "hi!"; }
}

//FileB.ts
partial class ClassA
{
   public sayBye(): string { return "by!"; }
}

will be:

partial class ClassA
{      
    constructor(public name: string) {}
    public sayHello(): string { return "hi!"; }
    public sayBye(): string { return "by!"; }
}
Out of Scope Suggestion

Most helpful comment

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.

All 224 comments

I think you employ "partial" on modules too and help resolve this issue raised here.

https://github.com/Microsoft/TypeScript/issues/447

@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.

@jfrank14, as suggested above by @basarat would #9 not work for you?

// File1.ts
class Dog { 
 ...
}

// File2.ts
extends class Dog {
  woof() { /* ... */ }
}

@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 "//

+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:

+1

+1

+1

+1

People randomly +1 this isn't going to move it on.

The use cases so far are:

  • I have really big classes that span multiple files. @RyanCavanaugh indicated that it was likely a major design issue with code that complex and not sufficient to warrant the complexity of implementation.
  • It like them.
  • An other argument seems to be C# has them.
  • The other argument is around generated code from other languages.

The second and third use case is not compelling and the fourth, I suspect needs some level of expounding how delivering #9 wouldn't meet a very similar requirement and even Decorators (#2249).

It does look like #9 would accomplish the same thing and be even more general (because you could extend classes other than your own). But it might be reasonable to want class content in two files (perhaps because one is hand written and the other generated by a template), and to say that both files define the essential members of the class with equal importance, and not require that one file "extend" the class define in the other.

It's an almost existential difference, but perhaps important to some people in some situations.

I don't want partial on classes for reasons stated, but on modules it makes sense IMHO.

https://github.com/Microsoft/TypeScript/issues/447

Partial classes are extremely useful for specializing use-cases. It is not a violation of any OOP pattern but a way to arrange code document, which provides:

  1. Ability to split the class/type definition in multiple files. For huge code files, it is maintainability++ feature.
  2. Opportunity for compiler/build-system to make use of conditional linkage at compile-time. Analogy MSBuild, concrete use-case in C#: DBML, designer classes and even more fancy stuff like https://github.com/dotnet/corefx/pull/2045/files.
  3. Inherent protection, so two (or more) developers don't run into each other during code check-in. Conflict resolution blows! :)
  4. Let you generate code into the main partial class, then create another partial for custom overloads. Works perfectly!

I believe in separating business logic and data layers into separate classes and I mostly use static methods in these layers. I really don't see how it could be more code and less maintainable.

While extension method is a core language feature influenced by OO patterns and will be processed at compile-time, partial classes deals with document/code-layout to be stitched at pre-compilation stage. Despite the similarities in partial classes, abstract classes and extension methods, there is a clear distinction.

:+1: for bringing the harmless "Partial Classes" to TypeScript.

My use case for partial classes is for code generation -- my team needs to be able to auto-generate part of the class in one file and add custom methods and properties by hand in another file. I'm a bit confused why @RyanCavanaugh is "not sure those kind of situations apply in JavaScript/TypeScript", since this use case is unrelated to the language of choice.

Neither decorators nor extension methods solve the code generation problem as elegantly as partial classes, and each has substantial additional complexities.

+1

+1

+1 for code generation purposes.

In the C# environment, the integration of a transpiler of C# classes to TypeScript classes would remove the need to keep two different definitions of classes between the server and client side as the client side, aka TypeScript class, would be automatically generated and the partial class that this issue is requesting would allow customization when needed while still developing in native TypeScript.

+1 for code generation scenarios

+1 extremely helpful for code generation

Why not use inheritance for code generation?

Inheritance is messier and has more overhead.

On Mon, Aug 10, 2015, 10:09 AM Gorgi Kosev [email protected] wrote:

Why not use inheritance for code generation?


Reply to this email directly or view it on GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment-129468291
.

​Inheritance creates useless name couplings

Inheritance is less awesome because it:

  1. Deepens the prototype chain needlessly and slows down instantiation,
    although thats not a big deal for most apps, likely everything but games;
  2. For lack of abstract and override either loses some type safety or
    introduces the need for some ackward patterns like casting between the two
    types;
  3. Is confusing overall as having a base class communicates the idea that
    it can be extended by other classes, which is rarely the case with codegen

Not saying typescript HAS to have partial classes to support codegen, only
that partial classes are so much better at it than inheritance or
composition.

@JoshMcCullough Inheritance overhead in JS is minimal, and I don't see how its messier than partial classes: with those you can potentially split a class into 10 files and chase your methods all over the place.

@yahiko00 What kind of "useless name coupling" are we talking about here? Do you refer to the things you'd need to do to get No. 2 below (hardcoding the name of the extended class)?

@hdachev

  1. There is some overhead, but its quite minimal - only noticeable if you're doing things that translate directly to a couple of machine instructions
  2. Good point - you don't get the extended class when you have to reference the generated class from other generated classes.
  3. Those classes are indeed meant to be extended - otherwise you could generate them and be done with it, right?

AFAIK this is not on the ES7+ radar, is it? That might be problematic...

In any case, attaching extra things to the prototype of an existing class is quite trivial in JavaScript and not at all uncommon, so it might be a good idea to have syntax for that...

It's straightforward in TS but the JS behind the scenes would double the
"protoyping" if you were using base classes for all of your generated data
objects. Probably not a serious performance impact unless you have a ton of
data objects, but it still is unnecessary when we know that "partial
classes" are possible.

On Mon, Aug 10, 2015 at 11:03 AM Gorgi Kosev [email protected]
wrote:

@JoshMcCullough https://github.com/JoshMcCullough Inheritance overhead
in JS is minimal, and I don't see how its messier than partial classes:
with those you can potentially split a class into 10 files and chase your
methods all over the place.

@yahiko00 https://github.com/yahiko00 What kind of "useless name
coupling" are we talking about here? Do you refer to the things you'd need
to do to get No. 2 below (hardcode the name of the extended class)?

class MyClass extends GeneratedMyClass { ... }

@hdachev https://github.com/hdachev

1.

There is some overhead, but its quite minimal
https://jsperf.com/prototype-chain-vs-direct-calls - only noticeable
if you're doing things that translate directly to a couple of machine
instructions
2.

Good point - you don't get the extended class when you have to
reference the generated class from other generated classes.
3.

Those classes are indeed meant to be extended - otherwise you could
generate them and be done with it, right?

AFAIK this is not on the ES7+ radar, is it?

In any case, attaching extra things to the prototype of an existing class
is quite trivial in JavaScript and not at all uncommon, so it might be a
good idea to have syntax for that...


Reply to this email directly or view it on GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment-129483174
.

@Davidhanson90 that file has zero classes in it. Did you mean to post this in a different thread?

I'll post onto the correct thread. https://github.com/Microsoft/TypeScript/issues/447

+1

+1

+100

+1

+1

+1 for code generation.
I have been getting into angularjs and webapi and I want to make a tool that essentially creates automatic JS definitions from my c# objects and services. I want to then be able to extend these classes without having to edit the "scaffolded" JS definitions. I've see that a few other people are requesting this and it seems like we have similar use cases.

+1 for code generation

+1 for code generation, angular has lots of boilerplate code, we're already doing lots of generation of it, but with partial classes we would be able to do much more.

+1 yet again for code generation. Trying to extend classes in another file is messy at best.

@RyanCavanaugh, what is needed to get this out of "+1" mode and moving in a productive direction?

-1 a following syntax is better for mixins: #2919

Not sure why can't we have both partial classes and the mixins; two totally unrelated features.

+1

This would be nice when code is generated, but you don't want to modify it to add things to the generated code.

+1

I have a proposal that should satisfy both of these use cases:

  1. You want to write methods of your own class in different places.
  2. You want to add new methods to someone else's class, e.g. a builtin.

For (2), normally you would just use the :: operator to get infix syntax.

But if you want an old class to be part of a new interface, or if you want to dynamically dispatch, you will need to actually modify the prototype.

interface ITimes {
    times(n: number): number
}

Array implements ITimes {
    times(n: number): number {
        return this.length * n
    }
}

// The compiler should check that all methods of ITimes and IOther are implemented.
Number implements ITimes, IOther {
    times(n: number): number {
        return this * n
    }

    other(): void {}
}

// The old types should typecheck with the new interface.
const x: ITimes = true ? [] : 0
x.times(3)

// The interface list can be empty. This essentially gives you partial classes.
MyClass implements {
    anotherMethod(): void {}
}

(In the example I use string method names, but since these are builtin types, using symbols would be better once those can be typechecked.)

An improvement that this has over true partial classes is that the class has a single definition, and other places merely extend it. This means there's a clear place to import the class from and makes translation to JS easier.

:+1: I would love to see partial classes too.

What is the status of this feature?

This use case for example :

I have a Math package that define a class Set, with methods Set#add, 'Set#remove'

// math.ts
export partial class Set {
  add(){}
  remove(){}
}

I have an optional, heavy, Relational package that define classes Relation and Tuple.

This Relational package would also add a Set#product method.

// relational.ts
///<reference path="./../math/tsd.d.ts"/>
partial class Set {
  product(){}
}

export class Relation(){}
export class Tuple(){}

Partial classes would allow me to compose classes in a more flexible way. If I don't want to use the heavy relational package, I can still use the basic Set functionality. Other partial classes will only come in and add extra functionality to the class.

I'm scratching my head to do something that will have a nice API without the use of partials in this case.

All I could come with is some repository pattern.

// Without partials

// base

export class Base {
    static registerOperation(opName, method){
        this.prototype[opName] = method;
    }
    operation(name, ...args){
        return this[name].apply(this, args);
    }
}

// math.ts
import {Base} from './base';
class Set extends Base{
    // Define the methods here
    add(){}
    remove(){}
}

// Or here
Set.registerOperation("add", function(...){});
Set.registerOperation("remove", function(...){});

// relational.ts
import {Set} from './../math/math';

Set.registerOperation("product", function(...){});

// app.ts

import {Set} from 'math';

var set = new Set();
set.add // compiler error
set.remove // compiler error
set.product // compiler error

// have to use something like
set.operation("add", args);
// or
(<any>set).add(arg);

+1 I'm using t4 to generate classes and proxies over WebApi. I think auto-generation is using vastly in typescript and when it comes to auto-generation, partial classes is necessary!

It would be great for splitting aspects of the same class especially in React
+1

+1 Code generation and "Just enough separation" in the case of pure reusable data objects with client-specific attributes for like validation that would be neat to have defined on the class but maintained in a separate piece of source code.

+1 for Code generation of partial classes and handcode additional members for these classes in separate files.

+1

+1 I have large base of methods in our js api service, it would be best to split them into files, which makes it easy to understand each method.

api service like fb (facebook) or gq (google analytics), where you are given one global class or object, which you can use through out your development.

+1

This feature would be a big plus for us too.

We developped a middleware where all types of clients can connect to, and communicate with our servers through it.

We generate some of the client code based on what is exposed by the servers.

So far, everything was ok. But now, we'd like to be able to transfer heterogeneous collections of objects (but with a same base class). The objects transfered are part of the code generated based on the server API.

To be able to use the power of inheritance, abstract methods are the key in this case. But our developpers won't add methods to generated code, i presume everyone knows why ;)

As far as i understood (i'm a C# developper), the solution proposed here (https://github.com/Microsoft/TypeScript/issues/9) would not allow us to do that.

So, partial classes would be perfect for us. We would generate the class as partial, and if developpers need to add logic or methods, they would just have to write an other part wherever they want.

+1

+1 very helpful for code generation

I wonder if module augmentation basically negates the need for this as a specific feature.

If you have a generated class then you should be able to do something like...

import {MyClass} from "./MyClass.generated"

MyClass.prototype.partialMethod1 = function() {
  return true;
}
MyClass.prototype.partialMethod2 = function(abc: string) {
  this.doSomething(abc);
}

declare module './MyClass.generated' {
  interface MyClass {
    partialMethod1(): boolean;
    partialMethod2(abc: string): void;
  }
}

@disshishkov That looks like a good way to implement it under the cover, but I'd still like proper first-class support in the language without the need to manually modify prototypes and maintaining that interface.

I agree with Elephant-Vessel. The manually crafted part of the partial class should be as loosly coupled (at design time in TS) as possible form the generated part.

The suggestion by @david-driscoll works for many cases. However, as far as I can tell, prototypes don't have access to internal variables. This limits the usefulness of this approach in code generation contexts where you want to generate the core parts of your classes and then augment them with custom code.

+1

@david-driscoll that looks like an excellent way to desugar this feature. (would need to add the ability to access to private/protected properties). Wonder what would happen with multiple partial class declaration? What would the mutual visibility of those be?

++ 1 Lack of partial is really hurting me when trying to extend my auto generated models..

I think the only thing in scope here is basically what @david-driscoll proposed -- you could declare new methods (which would be put on the prototype) and new _non-initialized_ properties (which have no codegen), but not new initialized properties (because these have side effects on the constructor codegen).

downvoted, pardon my french, partial classes are a stupid attempt to chunk your god classes, which are inevitable in OOP, into multiple files so that they are easier to manage (although still being god classes)

with OOP there is no future for you people (been there, know what i am talking about)

come to FP, we have cookies and a way to write a program without a single class and s**t like this

So we already basically allow this anyway through interface A { method(): void } A.prototype.method = function() { };; codifying this into a sugar for exactly that makes sense.

One thing to bikeshed is the keyword partial. A brief historical vignette: In C#, partial class was originally going to be extension class (which you put on all but one declaration), but there wasn't a clear distinction about which declarations would be the extension and which declaration would be the non-extension declaration. Instead you have the modifier partial that you must place on _all_ classes.

This is _not_ the case in TypeScript; rather the opposite. Here, only one class (let's call it the "_primary_ declaration") may have constructors / initialized member fields; the primary declaration doesn't get any new modifier. Every other declaration (let's call them "_extension_ declarations") may only have statics, methods, and non-initialized fields, and you'll _need_ to have some modifier on them to indicate that they're not primary.

The current best guess is

class Foo {
  x = 6; // only legal to initialize here
  constructor() { } // only legal to have constructor here
  someMethod() { }
}

// vvvvvvvvv thoughts?
   extension class Foo {
     someOtherMethod() {
     }
   }

:sparkles: :bike: :house: :sparkles:

Bikeshedding or not, this is sounding an awful like #311 which was walked away from because of likely interfering with future ECMAScript standards. Why is this worth considering, but proper mixin support isn't?

Using the keyword extension conflicts with extension methods? Or is this going to negate extension methods completely?

@kitsonk I think the mixin proposal has a lot more open questions. The partial class proposal here is just a codification of things that are already allowed in TypeScript, just with some syntactic sugar (this feature could literally be done as a syntactic remapping to things we already have).

@Elephant-Vessel I don't think extension methods are happening if partial classes happen. Classes are the only place where extension methods make sense given our constraints, and the proposed ES7+ bind operator is a better way to shoehorn in extension-like syntax.

@RyanCavanaugh: to me, it seems a bit constraining to require that one class is primary and the others not. If you want to partition your code so that one file contains all the methods of a class and the other contains all the properties, neither seems more obviously primary, and why should you be forced to choose? Isn't it cleaner to have partials where they're all equal in importance, and merged by the compiler?

@RyanCavanaugh ... I would do it exactly the same way c# does it... it works great for code generation... which i believe was the primary problem the feature meant to solve in c#... although my memory is fuzzy... never had any issues, it's been around for years, and is battle tested...

If partial/extended classes won't be able to have initialized fields, I think it would be extra neat to support something like partial methods that we know from C#, basically a lightweight contract specific for partial classes. So like:

public partial class MyGeneratedClass
 {
     partial void Initialize();
     public constructor()
     {
          //...
         this.Initialize();
    }
 }

 public partial class MyGeneratedClass
 {
     partial void Initialize()  { //... }
 }

The need to be able to partialize/extend third-party classes could be quite easily(?) solved by making the partial/extends generally optional but required for use of partial methods.

I think that this could bring some neat expressive and operative power to the concept that we want here.

Those who's looking for mixins.

Consider the object initializes proposal by means of which (and flow analysis) the mixins can be done elegantly, naturally, idiomatically right as far as JavaScript goes:

function enableBeingPositioned<a>(
   // hypothetical syntax
   something: a /* <-- before type */ => a & { x: number; y: number; } /* <-- after type */
): void { 
   something.x = 0;
   something.y = 0;
}
let value = {};
value.x; // <-- should not typecheck
enableBeingPositioned(value);
value.x; // <-- should typecheck

Languages such as Java don't offer partial classes/structs. It is a niche feature of C#. Imitating C# "partial class/struct" concepts to full extent is the best way to go here.
In pre-compilation step, the first thing the TS compiler could do is to stitch the partial code blocks in memory and then move on to the regular compilation pipeline route. This will be more than enough to qualify for v1.0.0-preview1.0000 of Partial Classes feature in TypeScript.
Anything beyond what C# is offering is something that can be introduced in later versions when the feature will evolve and outlive its trial/preview. The corner cases and the similar kind of obscure stuff can be discussed separately one at a time and we can worry about the fit&finish later... IMO.

I also agree doing both partial and extension classes exactly the way c#
does it is the best way to go in terms of syntax and semantics, both work
extremely well for their respective use cases. Partial classes improve the
usability of generated code. Extension methods improve the usability
of static methods that operate on interfaces, specified generics and third
party types. Both are really cool, but please remember they are not the
same feature, I'm saying this here because of the proposed syntax above.

Extension methods would allow one to do this (sry about lack of formatting,
typing on a phone):

extend MyType[] {
somethingSpecificToMyType() { ... }
}

extend WeirdThirdPartyDatastructure {
sameHere() { ... }
}

That among other things like being able to do use libs like underscore
without the cruft, which basically means reaping the syntactic benefits of
extending built-in types without actually poluting them.

So brief - lets not treat the two as one and the same, they are both very
cool but not the same thing. I'd personally love to have both in our
language.

By the way, as a side note, I imagine many people cringe at the idea of
code generation and are ready to explain to everyone that it has no place
in javascript because there are more idiomatic ways to achieve the same.
There are two ways in which code generation is of great help in some
projects, such as the one I'm working on right now.

  • In performance-sensitive projects, such as games, where you just do
    everything to max out your cpu budget with useful work, codegen helps a ton
    to generate code that is both simple to reason about and highly optimizable
    / monomorphic code that jits really well. For example, in an
    entity/component game engine, generated code can help with a ton of stuff
    like very fast boilerplate code for sticking components together, event
    dispatch, etc.
  • In big business apps, generated code helps to get extreme mileage out of
    the type system, for example by emitting methods with very specific
    signatures for database queries, etc, which maxes out compile time
    checks, helps a ton with refactoring and also greatly simplifies debugging
    because it allows you to step through very simple orchestration code.
  • The big one is when you're keeping some component in sync across
    multiple language environments, e.g. something related to messaging
    like protocol buffers, or just json message interfaces, etc.

As another side node for the benefit of anyone wondering what partial
classes have to do with codegen, the value of keeping the generated parts
of a class into a separate file comes from source control requirements -
the generated stuff is usually a rapidly changing build artifact and you
don't want it committed in your repo.

I like the idea of implementing this accordingly to a well known and tried model of this concept, just like what C# has. 'Imitation' has some negative connotations to it, but it has significant value if done intelligently. On the other hand, the 'intelligent'-part of that is to be aware of different circumstances and limitations, so I won't protest if partials for TypeScript does not exactly look like partials for C#.

@Elephant-Vessel, I agree that it needn't be a ditto copy of C# partials, the general design can be laid out first crafted around TypeScript / JavaScript flavor while taking maximum inspiration from C# partials. My suggestion is to go with the 'registering partial keyword' and 'stitching partials' as a first step, and ship it as an experimental/preview feature (so consumer don't start depending on it in production code right off the bat). Later, based on the community response, evolve the feature until it is prod-ready and RTM'd. If we worry about all kinds of tricky gotchas and scenarios before hand, then most probably it will delay the matter further.

+1 - For extending and maintaining generated objects.

+1 for maintaining generated code

I created polyfill and divided my large class.

Define a class as an interface.

export class C {
  constructor() {
  }
}
export interface C {
  m(): void;
}

Implement class members.

export default class extends C {
  m(): void {
  }
}

Merge implementations.

import {C} from './core';
import m from './member/m';

compose(C, m);
export {C}
import {assign} from './assign';
import {concat} from './concat';

export function compose<T extends new (...args: any[]) => any>(target: T, ...sources: T[]): T {
  return concat([target], sources)
    .reduce((b, d) => {
      void assign(b.prototype, d.prototype);
      for (const p in d) if (d.hasOwnProperty(p)) b[p] = d[p];
      return b;
    });
}

https://github.com/falsandtru/spica/commit/a6ff30da5319db5f25f703a29da48fc0f7dbe2fe

I think this is a terrible idea for one specific reason: it will make the already complicated rules for global, ambient, external, namespaced, and brittle declaration order dependent inheritance problems significantly worse. This is not C# and name resolution and member declarations is very different.

Perhaps use an object or namespace instead of a class, a la the revealing module pattern if you really need to do this. Otherwise your class is probably just too large.

Also decorators can be used to implement associations between generated code and hand written code.

Do you have other solutions?

I would love to see this added to TS too

+1 for code generation purposes (DTOs from a WCF service reference with additional partial class definitions)

+1 for code generation purposes. My use case is: I have React components whose render() functions are generated externally via react-templates.

With partial classes I could type-check such functions versus the main class (the Component). Without partial classes, the only thing I can do is binding the function to the main class and hope for the best.

With next TS 2.0, I was thinking that some code-generation cases might be covered with the this type feature.

For example in the case I described previously, instead of

partial class MyComponent extends React.Component<any,any> {
    render() {
        ...
    }
}

I can write

function render<this extends MyComponent>()
        ...
}
MyComponent.prototype.render = render;

+1 As a developer I want partial classes so that multiple templates can generate/modify the same class spread out over multiple files.

My comments were specifically in regard to partial classes, not to mixins. The two are fundamentally different. Partial classes are about breaking up physical code, mixins are about breaking up logical behavior into reusable traits enriching other objects at both the type and the value level.
I do not think think partial classes are a good idea for TypeScript. Mixins, on the other hand are a good idea, providing increased expressiveness and meshing extremely well with both TypeScript's type system and JavaScript idioms as pointed out by @aleksey-bykov

@wendellm can you think of a clean way to do this given that ES Modules are physical. Partial classes work well and make a lot of sense in a language like C# where modules are logical not physical. From the point of view of the CLR, namespaces don't exist, it's just that class names can have dots in them (source an interview with @ahejlsberg)

+1 I need partial class!

can we extension interface? interface can also have some implemented functions, just like Swift:

interface Rect {
    x: number
    y: number
}

extension Rect {
    area() => this.x * this.y
}

Swift version:

protocol Rect {
    var x: Float {get}
    var y: Float {get}
}
extension Rect {
    func area() -> Float {
        return self.x * self.y
    }
}

+1

Code generation and partial classes go hand in hand.

Inheritance is a poor solution to what is essentially a glorified #include directive.

Take Angular 2 for example. It will not read metadata from the parent class, making extension-by-inheritance impractical.

@tsvetomir that's an Angular issue not a TypeScript issue.

Inheritance is a poor solution to what is essentially a glorified #include directive

Yes inheritance is a poor solution, but the problem is using classes in the first place. They have their place but it is very limited. JavaScript classes are pretty weak and inexpressive compared to classes in other languages.

Typescript is not an"Angular" language... Never was

On Jul 23, 2016, at 9:46 PM, Aluan Haddad <[email protected]notifications@github.com> wrote:

@tsvetomirhttps://github.com/tsvetomir that's an Angular issue not a TypeScript issue.

Inheritance is a poor solution to what is essentially a glorified #include directive

Yes inheritance is a poor solution, but the problem is using classes in the first place. They have their place but it is very limited. JavaScript classes are pretty weak and inexpressive compared to classes in other languages.

You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com/Microsoft/TypeScript/issues/563#issuecomment-234753589, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AJPCIh7n2_0dt00kw-XJv7tc9LB0tPsIks5qYtH4gaJpZM4CcixK.

I don't see the issue as Angular specific in any way. It is a particular case in which partial classes may have helped.

The request originates from past experience with C# and the lack of familiar features. The comparison is inevitable as TypeScript makes no effort to distance itself from .NET. Some form of feature parity is expected by its users.

The request originates from past experience with C# and the lack of familiar features. The comparison is inevitable as TypeScript makes no effort to distance itself from .NET. Some form of feature parity is expected by its users.

@tsvetomir as a long time .NET developer, and as a passionate C# programmer, I fundamentally disagree.

The article you cited is not authoritative, and does not reflect any official material from the TypeScript team.

Furthermore, it directly contradicts the TypeScript design philosophy as stated by @ahejlsberg in numerous talks, interviews, and posts.

Additionally, the cited article's viewpoint reflects a fundamental misunderstanding as to the nature of TypeScript.
Ironically, the commonalities that C# does have with TypeScript are actually the same ones it has with JavaScript.
These commonalities are not class-based programming, but rather constructs such as closures and higher order functions.

C# or not, we need partial classes which will help TypeScript getting closer to Javascript's prototype features.

@yahiko00
TypeScript already has all of JavaScript's prototype features.
It is a superset.

There are several problems with the notion of partial classes in TypeScript, including

  1. Unlike C#, TypeScript (JavaScript) class definitions are imperative not declarative. They appear declarative, but they are not. This means they depend upon deterministic execution order.
  2. The ECMAScript module system is based on importing physical not logical code units.
    For example, lets say I have

_app/my-class-part-1.ts_

TypeScript export partial class MyClass { firstName = "John"; lastName = "Smith"; }

and
_app/my-class-part-2.ts_

TypeScript export partial class MyClass { fullName = this.firstName + ' ' + this.lastName; }

How can I import this class? Since I cannot import from either module, let us imagine a hypothetical abstraction in TypeScript that allows me to write
_app/main.ts_

TypeScript import { MyClass } from './my-class';

What would this mean? Even if the TypeScript compiler could infer that _app/my-class-part-1.ts_ has to be loaded before _app/my-class-part-2.ts_, it cannot make the importing of the individual parts invalid nor can it ensure they are imported in the correct order by an asynchronous module loader such as RequireJS or what will eventually be implemented in browsers.

The whole notion of partial classes is fundamentally at odds with the ECMAScript module system.

Update: It would need to perform arbitrarily complex dependency inference and emit some very odd JavaScript.

TypeScript already has all of JavaScript's prototype features.
It is a superset.

I should have expressed myself better. Of course we all know TypeScript is a superset of JavaScript. But I wanted to say that partial classes would help TypeScript classes to get closer to JS prototypes. For the moment, we can just have "static" and non extendable classes, whereas, with a prototype approach, we can extend class-like functions.

Importing partial classes would lead to extends the current ES6 syntax I agree. We could imagine something like this:

import { MyClass } from ['app/my-class-part-1', 'app/my-class-part-2'];

TypeScript classes are based on ECMAScript classes and thusly suffer from the latter's lack of expressiveness. Consider using functions, modules, "namespaces", or plain objects to accomplish what you need.

Functions is what we want to avoid with the notion of class.
Modules or namespaces bring simple extensibility and have not the same expresiveness as TypeScript's classes. Also, a namespace or a module cannot be instanciated. They do not serve the same purpose as classes.

@aluanhaddad I see what you mean regarding modules. A possible solution would be to allow only one of the files to export partial class while the rest contain only partial class definitions. You import it from the place its exported. From your example:

_app/my-class.ts_

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

_app/my-class.part.ts_

partial class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

_app/main.ts_

import { MyClass } from './my-class';

What's missing is a syntax to let the compiler know where to locate the parts. This is not an issue with C# where you process all files at once. This might be a special syntax, as the one used for declaration merging.

It's not required for partial classes to allow arbitrary definitions. They can be limited only to methods, properties and constructors, for example. This makes execution order insignificant and allows the compiler to throw an error if a member is duplicated.

I fail to see why Module Augmentation is not valid for these scenarios. It's worked very well for us with Rxjs5.

You simply create your base class, and then with your code generation, generate all the augmented methods you need on top of the base class. It doesn't matter if the generated code is pretty, no humans are supposed to write it.

Is it a perfect replacement for partial classes? I suppose not, but I don't see partial classes happening unless ECMAScript decides JavaScript needs them. The semantics for how partial classes are linked together between external modules alone hurts my head.

@david-driscoll to make it even better, added methods can have a this: argument declared, for a stronger type-checking.

In the cited example of Module Augmentation:

// observable.ts stays the same
// map.ts
import { Observable } from "./observable";
declare module "./observable" {
    interface Observable<T> {
        map<U>(f: (x: T) => U): Observable<U>;
    }
}
Observable.prototype.map = function (this: Observable, f) {
    // here "this" has the shape of the "Observable" class
}

Yeah. Rxjs doesn't quiet use it yet, because it's a 2.0 feature, and 2.0 hasn't been released yet. It's on my hit list later.

I see what you mean regarding modules. A possible solution would be to allow only one of the files to export partial class while the rest contain only partial class definitions. You import it from the place its exported. From your example:

_app/my-class.ts_

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

app/my-class.part.ts

partial class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

I like the syntactic concept but the problem is that you have just introduced a new _kind_ of source file that is consumed as a sort of implicit module, looks like a script, and has to be loaded in a specific manner.

What's missing is a syntax to let the compiler know where to locate the parts. This is not an issue with C# where you process all files at once. This might be a special syntax, as the one used for declaration merging.

Declaration merging works for _declarations_, not source files.

It's not required for partial classes to allow arbitrary definitions. They can be limited only to methods, properties and constructors, for example. This makes execution order insignificant and allows the compiler to throw an error if a member is duplicated.

All of these _are_ commonly order dependent.

Edit: That is to say that defining them modifies the class.

Probably someone mentioned this already, but another useful case is when you generate part of the class from some code generator, then you wish to manually add some more code directly in your implementation.
You don't really wish to do mixing or derived class.
It's still one class - just part is generated automatically other part manually.

BTW: if someone needs to generate TS types from C# classes you can check TypeScriptBuilder

Thanks for considering this!

I'm going to try out your TypeScriptBuilder ;)

My suggestion...

What if the compiler didn't try to find all parts? What if I had to import other parts and controlled everything?

/MyClass.partial.ts

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

MyClass.ts

// v- this would NOT throw an error because the definition is marked as partial
import { MyClass } from "./MyClass.partial";

export class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

Then...

  1. If I want to use MyClass I have to import it from MyClass.ts
  2. When compiled, MyClass.partial.ts will generate a javascript which extends MyClass.prototype like showed here before. But it exports a function which receives the prototype to be extended.
  3. MyClass.partial.ts is imported in MyClass after MyClass has been defined and it's extend function is called.

On a side note... there's nothing preventing me from generating the compiled code directly. But I loose all the greatness of Typescript.

@svallory I think that's definitely the right approach here. Specifically because you say the generated code will export a function which would cause the augmentation, it would work even with asynchronous imports because the functions can be called in the necessary deterministic order.

More generally, and I forget the issue where it was referenced, if assignments to the class prototype affected the shape of the class, there could be many benefits. This would improve mixin libraries, make decorators far more useful, and generally encourage less vertical hierarchies.

It could be tricky for the compiler to track all of this, but it probably could be made to work by being explicit as you suggest.

It would be an enhancement to the type system, with the partial classes use case falling out of that enhancement.

I've did it like the following:

I've did it like the following:
file1.ts
interface ifoo{
   a():void;
}
class foo implements ifoo{
   a() { /*do something*/ }
}
file2.ts
/// <reference path="file1.ts" /> //not necessary
interface ifoo{
   b():void;
}
foo.prototype.b =() => { /*do something*/ }
file3.ts
/// <reference path="file1.ts" /> //not necessary
interface ifoo{
   c():void;
}
(<ifoo>foo.prototype).c =() => { /*do something*/ }
consumer.ts
/// <reference path="file1.ts" />
/// <reference path="file2.ts" />
/// <reference path="file3.ts" />
let f = new foo();
f.a();
f.b();
f.c();

Module Augmentation still solves 90% of the problem here. Given @svallory's examples.

/MyClass.partial.ts

export partial class MyClass {
    firstName = "John";
    lastName = "Smith";
}

MyClass.ts

// v- this would NOT throw an error because the definition is marked as partial
import { MyClass } from "./MyClass.partial";

export class MyClass {
    get fullName(): string {
        return this.firstName + ' ' + this.lastName;
    }
}

The module augmentation would be something like...

MyClass.ts

export class MyClass {
    firstName = 'John';
    lastName = 'Smith';
}

MyClass.generated.ts

import { MyClass } from './test';

Object.defineProperty(MyClass.prototype, "fullName", {
    get(this:MyClass) {
        return this.firstName + ' ' + this.lastName;
    }
});

declare module './test' {
    interface MyClass {
        readonly fullName: string;
    }
}

It's a little more verbose than a partial class, but really the partial class would just be syntactic sugar for this implementation.

The only gotchas today you don't have would be:

  • You cannot access private or protected fields using the this: MyClass syntax.

    • This can be easily solved in generated code by casting to any.

    • Perhaps this is something that can be added, such that you can access protected members of this. There may be other rules around that.

  • The generated code looks a little more intimidating , but for the consumer, once things have been augmented, they would never know the difference.

EDIT: Keep in mind, this is TS 2.0+ syntax.

@david-driscoll I agree. I think that is simpler and I like that it doesn't introduce the additional syntax. As you know, I am opposed to partial classes as a specific language feature, but I do think it would be beneficial if TypeScript tracked assignments to prototypes in general and refined the shape of the object accordingly. I think your approach is the right way to split classes across multiple files.

@wongchichong Your example uses global class names and /// <reference path="..."/>. I don't think that will scale well, although you could use a namespace to improve the situation.
Code written as modules (that is external modules) is a very different beast because it involves a loader which needs to be aware of dependencies which are order dependent and implicit. That is why @svallory's suggestion is valuable, it requires a very minimal amount of manual wiring which makes the dependencies explicit.

What if someone does not use modules?

@pankleks partial classes are still a bad idea.

To clarify, I mean they are bad idea in language like JavaScript where class declarations are imperative, not declarative. Even if you're using namespaces, you're going to end up breaking your code into multiple files which means you to have to depend on the script tag order of those files for this to work at all.

In a language like C#, partial classes work well but that's because they're fundamentally different from classes in JavaScript.

It's mportant remember that in JavaScript, class declarations are not even hoisted let alone declarative.

Barring ES6, the "class" concept is defined by TS. JS has no notion of a class _at all_.
So its up to TypeScript to decide what a class can be, no?

Barring ES6,

We cannot bar ES6 when discussing TS language features, because one of the TS goals is to follow current/future ES spec.

True that :/

For large systems with code generated classes, i.e. Entities, service layer clients etc, partial classes as per the C# design, provide a very elegant solution when generated code needs to be extended with additional state and behavior. On my present project, where we have ~500 code gen classes, I miss this feature dearly.

I still don't understand why some people are so hostile against a feature that has been proven useful elsewhere, except saying "it is a bad idea".

It seems this hasn't been discussed much on esdiscuss, the only thread I found has 9 posts.

@yahiko00 It is not that I am hostile to the concept. As you say it is very useful in languages such as C#.

As an enthusiastic C# programmer, I find partial classes to be very helpful for certain tasks. However, they do not interfere with the other aspects of the language. They do not break key related abstractions such as namespaces, assemblies, and arbitrarily orderable type declarations.

JavaScript, on the other hand, has a module system that is nascent at best. Classes are a new and, I would argue, as yet not very expressive feature of the language, they need time to grow.

If we take a step back for a moment and consider extension methods, another powerful, and far more useful feature of C#, I would love to see them added to JavaScript but there are fundamental problems with doing so that have yet to be resolved.

When we reach a point where partial classes can be specified without breaking or severely constraining far more fundamental concepts such as modules, I will be all in favor of adding them.

That said, as @SaschaNaz points out, this _does_ need to be addressed in ECMAScript.

Maybe anyone interested can open a new thread on http://esdiscuss.org and post the URL here so that we can continue discussion there 😄

PS: Or on more-GitHub-like ES Discourse.
PS2: Or on also-GitHub-like-and-more-active WICG.

I too would love to see some construct that allows for code generation for TS. Partial classes work great for this in C#.

Maybe I am missing something, but it seems to me that the core issue is extending a class with access to 'private' variables from somewhere other than in the constructor, preferably from another file.

Based on the discussion it seems like much of the 'safe' TS innovation has been done. Now we are just waiting to see what the ES governance body does because we don't want to break anything going forward. Totally valid, but a little disheartening because I was hoping for a faster moving train with TS.

A prerequisite is finding a good desugaring:

Although I previously thought partial classes were pretty silly because you could just add to the class directly, I can see the appeal given that doing so will involve making your methods non-enumerable plus fixing the super binding (the latter of which is currently impossible in ES6).

We first need to figure out a good desguaring for classes in general into compositional, imperative primitives, like the old toMethod. But once we have that, adding some more sugar on top like partial classes might be reasonable, depending on how ergonomic---or not---those primitives end up being.

Not sure what this exactly means but probably like this:

class A {
  foo() { return "foo" }
}
class B extends A {
}

partial(B, class {
  get foo() {
    return super.foo(); // should work
  }
});

(Cross posted on esdiscuss)

It seems there is a fairly simple way to implement partial class in pure JS (with ES2017 getOwnPropertyDescriptors). ES people may think a syntax sugar will even not needed only to remove this tiny code.

function partial(base, extension) {
  extension.prototype.__proto__ = base.prototype.__proto__; // to enable 'super' reference
  const descriptors = Object.getOwnPropertyDescriptors(extension.prototype);
  delete descriptors.constructor; // must not override constructor
  Object.defineProperties(base.prototype, descriptors);
  
  return base;
}

Using this on TS requires an interface duplicate to extend existing class type, of course.

@SaschaNaz I expect that properties added to constructor through getOwnPropertyDescriptors will be hidden for IDE "autosuggestion" (since they are added at runtime). Remember, Typescript born as a JavaScript with "autosuggestion" (sometimes people call it "stronlgy typed" but really what they like is "autosuggestion").

P.S. Why people need partial classes - codegeneration. But again codegeneration should be supported both by IDE (easy "tool" adjusting to source file, hierarchical result in files explorer, T4 or similar "common codegenerator" support) and in language (partial classes, extension methods). Only after understanding this it is become possible to understand what developers really ask. If you do not see full picture - of course "partial classes" looks like "nonsense".

@aluanhaddad: but isn't TypeScript's main function is to provide us with language elements which are not present in JavaScript? Why is it a bad idea to have a class splitted into two partial TypeScript files, which will be compiled into a single JavaScript file?

I really do not see the problem with giving a tool to the community. And I am 100% sure there will be devs who will misuse it. But also devs who know exactly how to use it. But don't we have the same situation with any construct of any language?

+1 for code generation purposes. And I agree with @rpokrovskij, why we choose TypeScript, I can also use JavsScript directly, Just because it's seems like C#, and has ide support.

@greendimka I don't know how this could work without both diverging from and adding to substantial complexity to ES Modules.

@xiexin36 TypeScript sure seems more like JavaScript than C# to me.
There are commonalities between JavaScript and C#, but their notions of class are worlds apart.

@xiexin36 for code generation you can still use module augmentation (as I noted earlier in this thread). Syntactically it's not as "easy" as partial classes, but you can accomplish the same task.

@aluanhaddad Well, it works very simply: partial classes do not change the structure of code in any manner. They just allow us to write definition of the same class in several files (which are compiled into single JS anyways).

@aluanhaddad Strictly speaking: javascript has no concept of classes (ES6 classes just provide a syntatical sugar). So, if we try to follow the concept of having TypeScript as weak as JavaScript - shouldn't we throw away classes from TypeScript? Shouldn't we simply revert to JavaScript?

@greendimka ES6 classes and TypeScript classes are one and the same.
TypeScript does not aim to add additional constructs to JavaScript's runtime.

ES6 classes are _very_ lackluster. That doesn't mean that JavaScript isn't a powerful language (it is). TypeScript provides static typing to catch errors at design time, provide high quality tooling, allow extremely precise and rigorous specificaiton of component interfaces, and generally improve productivity.

ES6 classes are _very_ lackluster but for TypeScript to introduce its own notion of classes would be in direct violation of its design goals.

Simply avoid classes and your problem will be solved.

Well, it works very simply: partial classes do not change the structure of code in any manner. They just allow us to write definition of the same class in several files (which are compiled into single JS anyways).

And break almost every tool known to man? No thank you.

@david-driscoll Thank you, I will try it, but I also use Angular 2.0, I wonder if I generate code with
@Input or @Output , it will work, anyway I will try it.

@aluanhaddad it is a pain to see how you hanged on repeating "classes? javascript has no classes". Remove classes from your head, leave only JavaScript, and now listen: developers who use code generation want to have one compilation unit in several files. There are no classes in this language, only functions? OK, we want partial functions. And JavaScript is almost ready for this: functions there can be used before declaration. There we can meet other problems of course (e.g. to be sure that all parts/files are loaded to executiuon environment), but they are solvable, and actually we want to have partial compilation units in TypeScript, not in JavaScrpipt. Typescript is ready for this 100%.

And by the way, TypeScript team, give us partial functions also! And please tell the same to C# team, since we have there "functions in functions" for now. :)

Just to make sure, you do realize that partial functions have a very specific meaning and what you're describing are not partial functions by any stretch of the imagination?
Code generation is useful, I use it as well.

@aluanhaddad . Do you understand the term "one compilation unit in several files" ? Javascript of course is not compilation language but a) function should be fully parsed before execution and we can name this "compilation" b) Typescript is compilation language.

To help your imagination:

function partial func(arguments) {
  return function() {
    return codegenerated(arguments);
  };
}

function partial func(arguments) {
   function codegenerated(arguments){
      // ...
   }
}

I also do not use partial classes often: to use them effectively we need to store codegeneration parameters in "manual" part and to read this configuration we should have good language parser (not reflection). But that how it is: partial classes is only one instrument from many to make codegeneration comfortable.

@rpokrovskij
I apologize if I came off as antagonistic. I meant no offense or disrespect.

Your example has aspects which would require a fairly formal description in their own right. This proposal was not originally about directly enabling code generation scenarios.

@aluanhaddad....
"Simply avoid classes and your problem will be solved" - seriously, that is a solution to a problem?! Probably if I avoid using JavaScript - I can solve the problem of this whole discussion. Also a solution, isn't it? Unfortunatelly we have this shitty language in our universe because it was lucky enough to get into web many years ago. Anyway, this is an offtopic.

"break almost every tool known to man" - how is that possible??? How?!?! I try to imagine breaking something by using partial classes in TypeScript, but I cannot. I simply cannot. Please, help me here with some real life example.

Now imagine you have built a car to transport boxes. It works without any problems. You hire a worker, who loads up the car. The worker takes two boxes at a time and puts into the car. Still everything works fine.
One day the worker leaves for another company and you hire a new one. The new one takes a single box, loads it, takes another single box and loads it too. Logically: everything is ok. But you run around and scream: stop, stop, we have a system failure! :)

"Simply avoid classes and your problem will be solved" - seriously, that is a solution to a problem?! Probably if I avoid using JavaScript - I can solve the problem of this whole discussion. Also a solution, isn't it? Unfortunatelly we have this shitty language in our universe because it was lucky enough to get into web many years ago. Anyway, this is an offtopic.

ES2015 has many things wrong with it for sure. ES5.1 had many things wrong with it for sure. In my opinion, a lack of classes was not one of those things. My point is that by using techniques like the revealing module pattern you obviate the need for partial classes. TypeScript provides sugar for the revealing module pattern, namespaces.

"break almost every tool known to man" - how is that possible??? How?!?! I try to imagine breaking something by using partial classes in TypeScript, but I cannot. I simply cannot. Please, help me here with some real life example.

If you use ES Modules, this is problematic. Any tool that relies on the physical artifacts of the compiler having a correspondence with their uncompiled counterparts would be subject to this. That said, TypeScript could adjust for this in the emit, a massive change, but it would then be emitting JavaScript that did not match the TypeScript that you wrote.

So, basically, the evolution of a language is being hold back by the tools, which will never evolve without the evolution of the language.
Sorry, but I see here only the search for the reason not to evolve.

What are the benefits that partial classes give, that you can't already do with the language in a different way? It's nice syntactic sugar, sure, but what the true gains? Is there a concrete example other than to make it more like C#?


Aside: For the record I started as a C# Developer, moved to JavaScript / C# from there. Once TypeScript 0.8 was announced I was sold, not because it was C# for JavaScript, but because it was taking strict JavaScript and making it better for developers that enjoy the strong types of C#.

TypeScript is not C#, and should not strictly inherit features from C# just because C# has them. Just as C# should not inherit features from TypeScript. I can't count the times I've wanted features like union types in C# because they're so awesome for TypeScript, but they are not right for the language yet.


So far I've read Code Generation and Code Organization.

Code Generation, look at Module Augmentation there are some deficiencies I called out here but I'm sure they can be fixed.

Code Organization, I guess use regions (lol)? There are many other ways to organize you code, if you have one God class (for whatever reason) you can always split it up into many God classes. At the surface the god class is the import everyone sees and uses, under the covers however it's made of many classes perhaps as properties of the god class. If you are using partial classes for organization I would argue you need to refactor your code a little bit to try and SOLIDify your code.

I've been able to fit augmentation into most code generation scenarios I've encountered to date.

For Omnisharp-Client I use the interface extension here where OmniSharp.Api.V2 is a generated via reflection in C#. At the bottom of the file I have a tool that stubs out all the methods for that interface.

For RxJS we use to to map all of our methods that are on Observable.

I just can't reason around some of the issues with partial classes. For example if we are given 3 partial classes.

  • MyAwesomeClass1.ts
  • MyAwesomeClass2.ts
  • MyAwesomeClass3.ts

Scope: Global Module (using namespace / module)

Global compilation is where this appears to be the easiest. As TypeScript already merges namespaces together.

If my tsconfig.json only contains the file paths for Class1 and Class2 then anything that is in Class3 is not automatically merged in.

  • At first this seems like user error, but it won't immediately be apparent why the methods from Class3 are not included. This is a huge usability problem that will lead to confusion.

Scope: External Modules (import / export)

With external compilation, each file is really considered module (or hell Assembly in the .NET world) because each module has an explicit list of all it's dependencies (imports) and all of it's public api (exports).

How do you reason about these scenarios?

Given only one file reference, what is the behavior of the class?
Does it automatically merge Class2 and Class3?

  • Does the default definition of Class1, Class2 and Class3 all export the exact same value?
  • What file is emitted to disk?
  • What will the underlying JavaScript look like for all supported formats (amd, umd, commonjs, etc)
// somefile.ts
import { MyAwesomeClass } from 'MyAwesomeClass1';

new mac = new MyAwesomeClass();
mac. // What methods are available here?

Do we have to explicitly import all instances of the class? (If we do that defeats the purpose imo).
What happens when you import everything in one file, but not another, to the methods cary over?
This could lead to really strange errors given a complex dependency graph where the class is used once, without the extra partials. Would the values be augmented? or would the methods magically not work until the other file is loaded that brings them in?

// somefile.ts
import { MyAwesomeClass } from 'MyAwesomeClass1';
import { MyAwesomeClass } from 'MyAwesomeClass2'; // or maybe import 'MyAwesomeClass2';
import { MyAwesomeClass } from 'MyAwesomeClass3'; // or maybe import 'MyAwesomeClass3';

new mac = new MyAwesomeClass();
mac. // What methods are available here?

@david-driscoll Just my two cents here:

It's nice syntactic sugar, sure, but what the true gains?

Isn't nice syntactic sugar the whole point of any language? From an operative point of view, all we need is loops, if-clauses and iteration to do everything. The rest is just _nice syntactic sugar_ in order to be more productive and provide other similar non-functional qualities.

And while languages are generally good at the operational part of instructing a computer, they generally suck in the organizational part of writing code. We have these cultural ad-hoc artefacts like objects, classes, inheritance and such, but no solid theoretical foundation, afaik, that really explains the domain of organizing operations and all the abstractions we are trying to construct and represent in our source code in order to be able to work with it in a good way.

There is two things I love about TypeScript: 1. It lets us use typed javascript so that it's suddenly manageable to build complex systems in the client. 2. The type system is extremely expressive (because it was forced to be able to express all kinds of patterns in javascript that people could write without the limitation of a type system).

But in regards of structuring code, I don't think it's very significantly less sucky than any other language. And I wish we could be more innovative here. Give users more freedom to experiment with the organizational part of the language. Opening up to and striving for new structural expressiveness instead of being restrictive and suspicious.

Partial classes are not only very convenient for code generation specifically, but it increases the freedom in organization in general. Freedom which we need in order to get out of this tar-pit of code organization.

@david-driscoll what is the point of having partials? Well, once again: code generation.
What is wrong with your proposed solution? It is a workaround. Yet another workaround (and pretty dirty workaround). We already have a shitty language (javascrtipt), which is filled with workarounds. Instead of thinking about their main tasks, javascript devs spend a lot of time thinking about the workarounds. With your proposed philosophy we can throw away the whole TypeScript language. Because (surprise, surpsise) the whole types system can be simulated in pure javascript - by using workarounds. Why care about a more expressive language (like Typescript) if you can simulate anything with workarounds? Why write a single line of code when same thing may be written in twenty lines? Bring back the salaries based on a number of lines of code written! Short, expressive code is for pussies, isn't it?

And no: request to have partials in TypeScript is not based on idea that C# has them. I don't believe TypeScript should have something just for the sake of having it because another language has it.

And finally: why do you think that if you do not use something - nobody needs it?

@greendimka I wasn't trying to spark any hostility :shield:. I am simply trying to understand the scenarios or if there are ones I'm unaware of which frankly is entirely possible!

Now keep in mind, I'm not on the TypeScript Team, I'm just an advocate, but the team has been pretty silent here. The team may very well chime in when they have something specific to say, and I will defer to them if they choose to do so.

One of the key tenants that the TypeScript team has held to is try and keep TypeScript moving in sync with the direction of ECMAScript, and to avoid making any specific features that may cause them to diverge from the overall direction JavaScript is evolving to.

It's not that I wouldn't use it (I probably would if it existed). Problem is as it stands in this issue partial classes have may caveats so it seems doubtful it will be implemented any time soon. It will probably stay this way for a while until a) it becomes a must have feature for a high value stakeholder or b) a proposal steams into the later stages of TC39.

I don't see Module Augmentation as a work around. It allows you to augment the type system, and allows for many of the Code Generation scenarios that have been detailed in this thread. This is a stepping toward other language features.

  • Is it ugly? Absolutely, ugly as all hell. That said if you are generating the code, what is the difference? Only your generation tool needs to be worried about how to augment the class. Once you have run your code generation tool, and include your modules, you get full intellisense and compilation errors, etc.

  • Is it perfect? Far from it! I see a far more common scenario with mixins needing to be supported at the language level. And I think something line with decorators as proposed here makes sense, though again there isn't any specific proposal.

@david-driscoll, sorry for being extremely rude. I really tend to stand on a side of positive progress.

I would like this so I could put static implementations in a partial class.

Since it doesn't look like this will come to fruition soon, I would like to propose a workaround that we found. There are some comments like this, but I didn't see one with these specifics reading.

We would like Partials for use in a code generation scenario where we want to be able to extend our generated TypeScript code. However, we are generating models that have interdependencies so inheriting from our classes doesn't work well in the traditional sense. The generated classes that reference other classes don't end up with the right type of object being referenced and we would end up with a complex factory pattern to get the correct instance types created.

We ended up changing our generated classes to base classes, but only in the class declaration. We then created stub classes that inherited from our new base classes. We could then extend these new classes and they would inherit all their content from the base class.

For example:
If we generated a class Person, we would now generate a PersonBase. All the generated code goes in this class. We would also generate an empty class Person that extends PersonBase. This class would only ever get generated once. We then put all our generated code in PersonBase, and all the custom code manually goes into Person. All generated references to Person remain as Person and not PersonBase. This way all IntelliSense continues to work.

File 1: Base Class

module ViewModels {
    export class PersonBase {
        // Generated members
        public anotherPerson: Person;
        constructor(){
            // Generated constructor code
        }
    }
}

File 2: Actual Class

module ViewModels {
    export class Person extends PersonBase {
        // Custom methods
        public NewVariable: string = "NewVar";
        constructor() {
            super();
            // Custom constructor code
        }
    }
}

This has solved our partial class problem with generated code. Kudos to Andrew Scott for coming up with the idea.

I'd really like this too, since I'm generating some code with a code generator, and I need to add some changes to it. Partial classes will allow regenerating the code without having to add the changes again later (which might be big or complex)

There's an important reason to have partial classes which I don't think has been mentioned yet: gradually migrating JS to TS. In Javascript, particularly pre-ES6, classes can look like a bunch of:

Foo.prototype.someFunction = function() {/*....*/}

And these can be spread over multiple files without any special handling. Converting a codebase like that into modern TypeScript currently requires moving functions so that all the members of a class are in the same file, which can be a pretty invasive change. With partial classes, the migration could be done using only local edits.

@RyanCavanaugh You mention that everything asked for here can be syntactically handled with other TypeScript syntax:

I think the mixin proposal has a lot more open questions. The partial class proposal here is just a codification of things that are already allowed in TypeScript, just with some syntactic sugar (this feature could literally be done as a syntactic remapping to things we already have).

So how would one go about doing this in TypeScript?:
File1.ts:

// Imagine this file is code generated and could be regenerated during development
export partial class Contact
{
    firstName: string;
    lastName: string;
    partial OnInit( args: any ) : void;
    constuctor( args: any )
    {
        this.OnInit( args );
    }
}
export class Address
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}

File2.ts

// See where I'm going with this? This file would be hand edited and allows me to specify associations and children.
partial class Contact
{
    Addresses: string[] = [];
    partial OnInit( args: any ) void
    {
        this.firstName = args.firstName;
        this.lastName = args.lastName;
        this.Addresses.push( new Address() );
    }
}

Transpiling the above would emit one JS class for Contact, something like this:

var Contact = (function () {
    function Contact() {
         this.Addresses = [];
   }
   Contact.prototype.constuctor = function (args) {
       this.OnInit( args );
   };
   Contact.prototype.OnInit = function (args) {
       this.firstName = args.firstName;
       this.lastName = args.lastName;
       this.Addresses.push(new Address());
   };
   return Contact;
})();

var Address = (function () {
    function Address() {
    }
    return Address;
})();

Note that in the end I want one class named Contact and I don't want to have to subclass two separate classes into a third.

@cosmoKenney

Here's an example of something that will work. It's not as syntactically surgared as partial is however it works and is a very functional solution.

// address.ts
export class Address
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}
// contact.impl.ts
import { Address } from './address';

// Class implementation, do the things here that are not code generated
export class Contact {
    firstName: string;
    lastName: string;
    addresses: Address[];
    constructor(args: any) {
        this.onInit(args);
    }
}
// extending the interface here
// define methods you know will need in the constructor only
// This only applies to the constructor however
export interface Contact {
    onInit(args: any): void;
}
// contact.partial.ts
import { Contact } from './contact.impl';

// Implement the extended contract here
Contact.prototype.onInit = function(this: Contact, args: any) {
    this.addresses = args.addresses.concat();
    // do stuff;
};

// Adding another method (not part of the extended interface)
Contact.prototype.somethingAwesome = function(this: Contact) {
    // do awesome stuff here
};

// Tell TypeScript "I added this here!!!!"
declare module './contact.impl' {
    interface Contact {
        somethingAwesome();
    }
}
// contact.ts
import { Contact } from './contact.impl';
import './contact.partial';

// Bring it all together (perhaps there are more than one partial class?)
export { Contact };
// main.ts
import { Contact } from './contact';

// use the contact!
const contact = new Contact(['my', 'args']);
const {firstName, lastName} = contact;
contact.somethingAwesome();

Alternatively you could also code generate the interface and use the interface extension implement that.

There may also be ways to use the new Mixin functionality, however I have not dived into that yet myself enough to give a qualified answer.

@david-driscoll Wow. My head just exploded.

I wonder if community will end up with a fork, which simply supports partial classes without blowing out a problem out of it.
So far have not heard any real arguments against partial classes. Only few reasons to justify a laziness.

@greendimka

I wonder if community will end up with a fork, which simply supports partial classes without blowing out a problem out of it.
So far have not heard any real arguments against partial classes. Only few reasons to justify a laziness.

Not sure what you are trying to say here. But if the overall feeling within the community is that we can achieve the same results using existing language features, then I just need some examples of how to do it. What @david-driscoll posted above is way beyond my comprehension. And doesn't seem to completely solve the problem. In fact, from what I can tell, he misinterpreted my intentions.
My primary concern is to code generate the scalar properties of the class, like a pojo or model class. But I need to be able to, in a separate file, or even in the same file, but not within the primary class definition add in the association properties (so that I can paste a newly code-generated primary definition over the original).
For example my Contact class from above would get code generated with firstName and lastName. But, in my separate definition is where I would add the definition and initialization of the collection of Address objects.
My code generator only knows the attributes of the class, not the associations, so it cannot code gen the addresses collection -- like was done in david's example.

@cosmoKenney it wasn't entirely clear where the address should exist. Forgive me to getting the context wrong. I'm just trying to help give the alternatives. There is plenty of functionality that allows similar behavior without putting something into the compiler like partial classes, which have a lot of additional considerations and potential problems to implement both module systems (internal / external).

In your case generating an abstract base class, or interface generation would work, then your other class inherits from that. Then the fact that your class was generated is still hidden.

ie:

// address.partial.ts
export interface IAddress
{
    addr: string;
    city: string;
    state: string;
    zip: string;
}

// address.ts
import { IAddress } from './address.partial';

export class Address
{
    constructor(args: any) {

    }
}
export interface Address extends IAddress{}

// contact.partial.ts
import { IAddress } from './address.partial';

export interface IContact {
    firstName: string;
    lastName: string;
    addresses: IAddress[];
}

// contact.ts
import { Address } from './address';
import { IContact } from './contact.partial';

// Class implementation, do the things here that are not code generated
export class Contact {
    addresses: Address[] = [];

    constructor(args: any) {
        this.firstName = args.firstName;
        this.lastName = args.lastName;
        this.addresses.push( new Address("address?") );
    }

    public somethingAwesome() {
        //
    }
}
export interface Contact extends IContact {}

// main.ts
import { Contact } from './contact';

const contact = new Contact(['my', 'args']);
const {firstName, lastName} = contact;
contact.somethingAwesome();

@cosmoKenney: @david-driscoll offers an interesting solution, but it still lacks the ease of real partial classes. As my personal experiments have shown - devs simply do not use "partials" which are made in this way. While it is a good workaround solution, the ease and comfort of partials is not there.

At the moment I do not know how TypeScript compiler works internally. I can only assume that it reads all source files, proceeds them, and outputs JS files. If it is so - I see no problems in reading single class from several source files. If two or more source files of a single class provide conflicting code (f.e. same property defined twice), compiler simply throws an exception. Just as it does if you write syntactically invalid code.

@greendimka, @david-driscoll
I tried to compile David's example from above, and ts doesn't like it:

C:\TestProjects\TypeScriptFakePartialClassTest>tsc -m amd address.partial.ts address.ts contact.partial.ts contact.ts main.ts
address.ts(4,14): error TS2300: Duplicate identifier 'Address'.
address.ts(10,18): error TS2300: Duplicate identifier 'Address'.
contact.ts(7,14): error TS2300: Duplicate identifier 'Contact'.
contact.ts(11,14): error TS2339: Property 'firstName' does not exist on type 'Contact'.
contact.ts(12,14): error TS2339: Property 'lastName' does not exist on type 'Contact'.
contact.ts(20,18): error TS2300: Duplicate identifier 'Contact'.
main.ts(5,8): error TS2459: Type 'Contact' has no property 'firstName' and no string index signature.
main.ts(5,19): error TS2459: Type 'Contact' has no property 'lastName' and no string index signature.

Besides I agree with @greendimka that this is too complex to use hundreds of times in a large application.

@greendimka I don't know how the compiler works too, but don't underestimate the task. JavaScript is not .NET and modules are not globally available (you should literally import them)

I'd love to see this implemented, but this task brings up several things that needs to be carefully thought about, like:

  • If you define part of the class on a file A, part on file B, which one should contain the full class after tranpiling? A new one should be generated?
  • Should all the files that contains partial stuff export the same class?
  • How to avoid cyclic dependencies if I require the main file on those additional ones?
  • What if I export more things on module than just the class itself?
  • Name conflicts checking?

and so on...

@greendimka See my responses below: (EDIT: this was targeted at @WoLfulus, sorry @greendimka):

If you define part of the class on a file A, part on file B, which one should contain the full class after tranpiling? A new one should be generated?

I would be perfectly happy to have file A.js have the full definition, and file B stubbed off. Maybe with a canned comment. Most of us are bundling anyway so the myriad .js files that get bundled become essentially an after thought in the end.

Should all the files that contains partial stuff export the same class?

This is pretty much answered by my response for the first question.

How to avoid cyclic dependencies if I require the main file on those additional ones?

I don't know. Isn't it the module loader's job to recognize this scenario?

What if I export more things on module than just the class itself?

I don't see the problem with this. In other words if B.ts has both a partial definition and some other non-partial classes, then B.js should contain the canned comment as mentioned above, AND the definitions of the non-partial classes. Simple, I think.

Name conflicts checking?

How would you end up with a name conflict? If you mean on the class, then the "partial" keyword would resolve that. But then if two other files both defined classes with the same name, but without the "partial" keyword, the compiler should emit an error about duplicate types -- as it does now. But if you are talking about two partial definitions of the same class defining a property or method of the same name, the compiler should emit an error about duplicate members -- as it does now.

@WoLfulus, @cosmoKenney has answered well. Just to make it better with your first question (about A and B files): as a language designer, one has a privilege of defining rules. By that I mean that file A may have such code "partial class X" and file B may have such code "partial(fileX) class X", which will produce fileX.js.

@cosmoKenney

How to avoid cyclic dependencies if I require the main file on those additional ones?
I don't know. Isn't it the module loader's job to recognize this scenario?

TypeScript does not have a module loader.

@greendimka

I wonder if community will end up with a fork, which simply supports partial classes without blowing out a problem out of it.
So far have not heard any real arguments against partial classes. Only few reasons to justify a laziness.

That is not a good idea. For example, have you considered how you will you maintain your fork when dynamic imports are added?
Also, plenty of arguments have been made against partial classes. Breaking the source to source correspondence between TypeScript and JavaScript files goes against a key tenet of the language. I imagine that a feature would need to enable a scenario infinitely more valuable than partial classes for that to even be considered. It would likely still be rejected.

@WoLfulus, @cosmoKenney has answered well. Just to make it better with your first question (about A and B files): as a language designer, one has a privilege of defining rules. By that I mean that file A may have such code "partial class X" and file B may have such code "partial(fileX) class X", which will produce fileX.js.

I don't think you are getting your message across. That makes it sound as though you feel that any limitations you ever encounter expressing yourself in any language exist for entirely arbitrary reasons.
Also @WoLfulus' questions were not answered, at least not to my satisfaction.

dons flamesuit

TL;DR: This isn't happening. If you're down here at comment number 189 and want to register your disapproval with that, please do read the entire thread first, because the very good reasons for not adding this have been extensively covered above.

Our interpretation of this situation is as follows:

  • TypeScript already has too many TS-specific class features (constructor property declarations, member initializers, non-finalized decorators, access modifiers, implements, etc.) for something that was really intended to just be "ES6 + Types". Part of that is our fault (our original design direction was generally too OOP) and part of that is ES6's fault (the class proposal moved around a lot five years ago and we ended up having features that didn't make it). Adding yet another TS-specific class feature is another straw on the camel's back that we should avoid if we can.
  • Unambiguously, the future of JavaScript is modules. Partial classes only make sense and operate well in the "global soup" model. Allowing partial classes spanning multiple modules is a recipe for disaster as the loading order is not predictable. Adding a feature that only works well in a global-only universe isn't a good use of time.
  • C# has it but we're not here to reinvent C#. Seriously!
  • The "generated code" scenario isn't compelling on the merits. Any plausible emit for partial classes would restrict property initializers and constructor code to exactly one declaration, and this would be a dealbreaker for .Designer.cs-style setups as both the user code and the generated code would likely need initializers or constructor logic.
  • There are many, many other compositional mechanisms available in JS - mixins, Object.assign, etc.. The scenario that led to this feature in C# was driven by constraints that simply aren't present in JS.
  • The current workaround of interface + prototype.method = ... does enable the generated-code scenario just as well as partial class would. It's weird to write that code by hand but there's no problem for generating code differently, so if you really think a split-file generated code setup is the only way to solve your problem (I'm skeptical) then that method is available to you.
  • We consider ES6 to be the arbiter of "must have" for classes. There's nothing special about TypeScript (other than its appeal to C# programmers) that make it need partial classes any more than non-typed JavaScript would. So if there's some scenario that really knocks it out of the park for adding partial classes, then that scenario ought to be able to justify itself through the TC39 process. If that gains traction we'd be happy to weigh in with input on it, but this doesn't even seem to be on anybody's radar.

@RyanCavanaugh about this:

The current workaround of interface + prototype.method = ... does enable the generated-code scenario just as well as partial class would.

As I've mentioned more than once, I'm fine with there being a non-partial, non-c# way of accomplishing what I need, and just ask for a working example. david-driscoll was very helpful, but posted code that doesn't compile. So if you think I can code generate a class with scalar properties only for, for example, first, last name -- like above -- that's fine. I just need a way to add a collection of other types as a property on the class by hand coding that. But I also need a way to handle initialization of that set.

@cosmoKenney are you site you copied the right code? The second example had interfaces instead of the same class name. I can attach a zip of the code if you like. I was just hesitant because random files on the internet could be bad and didn't want you to think I was posting something malicious 🙂

Sorry to hear this, but I respect the design decisions made here. I have a couple of questions if that is ok:

TypeScript already has too many TS-specific class features (constructor property declarations, member initializers, non-finalized decorators, access modifiers, implements, etc.) for something that was really intended to just be "ES6 + Types". Part of that is our fault (our original design direction was generally too OOP) and part of that is ES6's fault (the class proposal moved around a lot five years ago and we ended up having features that didn't make it). Adding yet another TS-specific class feature is another straw on the camel's back that we should avoid if we can.

Considering this, would a possible way forward be to clearly distinguish, organizationally and code-wise, between the pure typing of JS, and the other language constructs that TS offers? I for one love both the typing and the extra language features. As a consumer/developer, I don't care much about about the fact the TS adds stuff that isn't there in JS. Just give me awesome stuff, if TC39 don't want it, I don't care.

If TS would encapsulate these things from each other, maybe that would be easier to reuse and be forked and built upon by projects like SoundScript, instead of replaced?

And then other project could build upon this typing to provide better/other language constructs than are offered by JS.

Unambiguously, the future of JavaScript is modules. Partial classes only make sense and operate well in the "global soup" model. Allowing partial classes spanning multiple modules is a recipe for disaster as the loading order is not predictable. Adding a feature that only works well in a global-only universe isn't a good use of time.

Is it really? Sure that modules would will be a natural part of JavaScript, but what about the main original body of code? I love namspaces and there is no soup in it if done properly. I'm compiling it all into one file, and I have no need of module loaders and in almost all cases no need of asynchronous module loading. Some stuff proposed like https://github.com/Microsoft/TypeScript/issues/420 would only be possible and relevant with namespaces. Are you saying that stuff like this aren't going to happen because we should only use modules? Are namespaces on the road to deprecation?

@david-driscoll Thank you, you've already been helpful enough. Since @RyanCavanaugh is the one who keeps closing the issue and stating that there are work arounds, maybe he should provide an example work around.

I'm also seeing a lot of misconceptions about what partial classes are. It's really a simple construct, and everyone is blowing this out of proportion:
https://msdn.microsoft.com/en-us/library/wa80x488.aspx

Considering this, would a possible way forward be to clearly distinguish, organizationally and code-wise, between the pure typing of JS, and the other language constructs that TS offers? I for one love both the typing and the extra language features. As a consumer/developer, I don't care much about about the fact the TS adds stuff that isn't there in JS. Just give me awesome stuff, if TC39 don't want it, I don't care.

That would be a rewrite of a language and break everyones code.

Also the "Just give me awesome stuff" is very fundamentally different than the design goals for TypeScript. If you just want awesome stuff and don't care about alignment to JavaScript you should choose a different language, like CoffeeScript, Dart, or Haxe. Of course there maybe reasons why those aren't doing as well as TypeScript in adoption...

one who keeps closing the issue and stating that there are work arounds, maybe he should provide an example work around

There are a lot of use cases for what a partial solves. Almost any language construct has lots of use cases it is valid for, but for good reasons, you have to pick and choose.

You keep asking for a specific language feature, as in "I would love a green car" but aren't getting to the crux of the issue, why does the car need to be green? If you explained why your car needs to be green, or be open to the fact that you don't actually care what colour your car is, as long as it provides for your real needs.

I don't see why you feel it is Ryan's obligation to tell you how to repaint your car, just because for valid reasons the car company has decided not to produce green cars.

(Oh and the mixin classes added in TypeScript 2.2 are a good way of accomplishing what I suspect is your real need)

interface Base {}

interface Constructor<T> {
    new (...args: any[]): T;
    prototype: T;
}

interface PartialClass {
    foo(): void;
}

function PartialClass<B extends Constructor<Base>>(base: B): B & Constructor<PartialClass> {
    return class extends base {
        foo() {
            console.log('foo');
        }
    };
}

class MyBase {
    bar() {
        console.log('bar');
    }
}

const MyPartialBase = PartialClass(MyBase);

const instance = new MyPartialBase();

instance.bar();
instance.foo();

@kitsonk mixins are not the same thing.

  • Mixins are self-contained units that can be added to existing classes.
  • Partial classes can access members from any other partial, as if they are part of the same class.

As an exercise, try to implement the following code split with mixins:

partial class Point {
  readonly x: number;
  readonly y: number;
}

partial class Point {
  translate(dx: number, dy: number): Point {
    return new Point(this.x + dx, this.y + dy);
  }
}

As an exercise, try to implement the following code split with mixins

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);

@Elephant-Vessel

Considering this, would a possible way forward be to clearly distinguish, organizationally and code-wise, between the pure typing of JS, and the other language constructs that TS offers?

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.

Are you saying that stuff like this aren't going to happen because we should only use modules? Are namespaces on the road to deprecation?

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' prototypes", maybe we'd feel differently.

@RyanCavanaugh

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.

@RyanCavanaugh

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...

@kitsonk

You keep asking for a specific language feature, as in "I would love a green car" but aren't getting to the crux of the issue, why does the car need to be green? If you explained why your car needs to be green, or be open to the fact that you don't actually care what colour your car is, as long as it provides for your real needs.

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.

I don't see why you feel it is Ryan's obligation to tell you how to repaint your car, just because for valid reasons the car company has decided not to produce green cars.

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#.

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

🤔

@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...
With inheritance and naming, I can do:

class AddressBase // this is a code generated class
{
    public address: string;
    public city: string;
    public state: string;
    public zip: string;

    constructor( jsonFromService: any )
    {
        this.OnInit( jsonFromService );
    }

    OnInit( jsonFromService: any )
    {
        // could use Object.assign here
        this.address = jsonFromService.address;
        this.city = jsonFromService.city;
        this.state = jsonFromService.state;
        this.zip = jsonFromService.zip;
    }
}

class ContactBase // this is also a code generated class
{
    public firstName: string;
    public lastName: string;

    constructor( jsonFromService: any )
    {
        this.OnInit( jsonFromService );
    }

    OnInit( jsonFromService: any )
    {
        // could use Object.assign here
        this.firstName = jsonFromService.firstName;
        this.lastName = jsonFromService.lastName;
    }
}

// classes that extend the functionality of the code generated classes:
class Address extends AddressBase // subclass simply because I don't want to have to use AddressBase all over my codebase, and then refactor if I ever extend the class
{
}

class Contact extends ContactBase
{
    public Addresses: Address[] = []; // THIS is the customization/extension that cannot be code generated.

    OnInit( jsonFromService: any )
    {
        // note that jsonFromService receives a dto with a array of address info
        super.OnInit( jsonFromService );

        for ( let addr of jsonFromService.Addresses )
        {
            this.Addresses.push( new Address( addr ) );
        }
    }
}

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":

partial class Point {
   readonly x: number;
   readonly y: number;
}

File "Point.codeByHand.ts":

partial class Point {
  constructor(x: number, y: number) {
      this.x = x;
      this.y = y;
  }

  translate(dx: number, dy: number): Point 
  {
      return new Point(this.x + dx, this.y + dy);
  }
}

They compile into "Point.js" - and the name comes from the name of a class, not from the names of files:

var Point = (function () {
    function Point(x, y) {
        this.x = x;
        this.y = y;
    }
    Point.prototype.translate = function (dx, dy) {
        return new Point(this.x + dx, this.y + dy);
    };
    return Point;
}());

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 :/

@greendimka

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".

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...

@cosmoKenney

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#.

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.

@aluanhaddad

I think you're perhaps misunderstanding the definition of classes in JavaScript...

For citated and below: I am talking about the TypeScript.
As I said: I do not see any technical problem implementing real partial classes in TypeScript, which will be compiled into constructs of JavaScript.

@greendimka

For citated and below: I am talking about the TypeScript.
As I said: I do not see any technical problem implementing real partial classes in TypeScript, which will be compiled into constructs of JavaScript.

The problem with this satatement there is no such thing as a TypeScript class.

Oh, boy! Some people will use anything as a reason.
Ok, there are no classes in TypeScript. Or TypeScript classes. Or whatever. Whatever.

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.

I think we don't mean the same thing when we speak of classes and that causes cognitive dissonance and impedes mutual understanding..
Totally agree!

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.
In relation to A and B. I hate JavaScript. But I know it very well and, of course, I know how classes are "represented" in it. But the point of this whole discussion was not to modify the JavaScript, but to improve abilities of TypeScript, as a higher language, which produces "low-level" JavaScript code.
Imagine we would replace TypeScript with C++ and JavaScript with machine code. Machine code lacks most concepts which exist in C++. But should C++ stop evolving because of it? Of course no. Should it stop evolving because some old compilers will not be able to compile? Of course no - you give a new feature to developers and tell them: it works with new compilers - you (developers) decide if you want to use it.

@aluanhaddad
Man oh man. Who cares about the Javascript part of the equation? TypeScript is a layer above, or however you want to phrase it. Remember the old 4GL vs. 3GL discussions? TypeScript is to Javascript as a 4GL is to a 3GL, kind of. Also the argument that TypeScript is ES6 with strong types, thus Partial Classes is outside the scope of TypeScript's roadmap is LAME. We got Mixins, Generics, Modules, Name Spaces and Type Casting. So why not go the extra mile with Partial Classes?

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.
One of the primary problems with adding this feature at the TypeScript level is that it breaks existing tools such as loaders and packagers. On the other hand, if ECMAScript specified them, then all of these tools would implement the feature and TypeScript would remain compatible with all of these tools.

I definitely agree with you regarding Scala.js

@cosmoKenney

We got Mixins, Generics, Modules, Name Spaces and Type Casting. So why not go the extra mile with Partial Classes?

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

@cosmoKenney

@aluanhaddad why do you keep making this out as a run-time thing? Module loaders and all that have nothing to do with transpiling.

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).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wmaurer picture wmaurer  ·  3Comments

siddjain picture siddjain  ·  3Comments

manekinekko picture manekinekko  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

zhuravlikjb picture zhuravlikjb  ·  3Comments