Typescript: Cours partiels

Créé le 29 août 2014  ·  224Commentaires  ·  Source: microsoft/TypeScript

Ajout de la prise en charge des classes partielles. Les mixins ne sont pas les mêmes, car c'est la réalisation au moment de l'exécution. Besoin d'une réalisation de compilation, où des classes partielles seront combinées en une seule avant de convertir le script dactylographié en 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!"; }
}

sera:

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

Commentaire le plus utile

Un cas d'utilisation pour les classes partielles concerne les classes proxy générées. Par exemple, les wrappers WebAPI ou SignalR. Ce serait vraiment bien de pouvoir étendre les classes proxy générées avec une logique personnalisée. Surtout lors de la génération de classes pour les modèles, il serait bien de pouvoir attacher la logique métier directement aux classes de modèle renvoyées par l'api.

Tous les 224 commentaires

Je pense que vous utilisez également "partial" sur les modules et aidez à résoudre ce problème soulevé ici.

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

@disshishkov peut-être que les méthodes d'extension suffisent : #9

Pour quel type de situations voulez-vous l'utiliser, et comment les solutions existantes n'y parviennent-elles pas ?

Notez que cela a été implémenté en C# pour prendre en charge les scénarios d'édition de type WinForms où vous avez un fichier généré automatiquement et un fichier édité par l'utilisateur contribuant au même type ; Je ne suis pas sûr que ce genre de situations s'applique en JavaScript/TypeScript.

Certaines classes peuvent avoir plusieurs numéros de ligne, juste pour une meilleure lecture, le fractionnement en plusieurs classes distinctes sera utile. Vous pouvez diviser par type différent, par exemple par logique (dans le cas où cette logique ne peut pas être déplacée vers une autre classe), par visibilité (privée et publique) et autre. Dans le cas où le peignage de classes partielles peut poser des problèmes (par exemple, 2 classes partielles identiques à la même déclaration de méthode/variable), le compilateur doit notifier et générer une erreur.

Ce n'est pas vraiment convaincant. Si votre classe est si grande qu'elle ne peut pas être modifiée confortablement dans un seul fichier en raison de sa taille, c'est une odeur de conception très importante (par exemple, les commentaires dans http://programmers.stackexchange.com/questions/157482). Le fractionnement par type/logique/visibilité/etc. est quelque chose qui peut être géré par un IDE ou par organisation au sein d'un seul fichier.

Cela vaut la peine de discuter de la raison pour laquelle vos classes sont si grandes qu'elles ne peuvent pas être parcourues (est-ce parce que les outils de navigation devraient être meilleurs ?), et s'il existe de meilleures façons pour le langage de prendre en charge la _décomposition_ d'une classe plutôt que de simplement la _séparer_.

Personnellement, je pense que les "classes partielles" devraient exister, mais se comporter comme des modules qui fusionnent. J'ai un système avec des modules qui, bien qu'intellisense voie tous les modules (comme il se doit), le JS qui le contient n'est chargé qu'en cas de besoin. Je pense que ce serait aussi bien pour les cours - de ne charger que les pièces nécessaires. J'ai également voulu créer une fonction et utiliser une classe pour la développer davantage. Actuellement, vous ne pouvez le faire qu'avec des modules.

Un cas d'utilisation pour les classes partielles concerne les classes proxy générées. Par exemple, les wrappers WebAPI ou SignalR. Ce serait vraiment bien de pouvoir étendre les classes proxy générées avec une logique personnalisée. Surtout lors de la génération de classes pour les modèles, il serait bien de pouvoir attacher la logique métier directement aux classes de modèle renvoyées par l'api.

+1 kvantetor.

Le cas d'utilisation est exactement le même que .net ; une partie de la classe est générée (dans notre cas, à partir de schémas Avro) et vous souhaitez ajouter un code d'aide supplémentaire pour travailler avec les classes générées.

J'aime cette proposition. J'aimerais avoir des classes partielles afin de séparer les attributs/propriétés des classes formant ma "hiérarchie de données" qui pourraient être regroupées dans un seul fichier, de leurs méthodes qui peuvent être réparties dans plusieurs autres fichiers. Cela rendrait le code plus clair et plus facile à comprendre en un coup d'œil imo.

Mon fichier de hiérarchie de données :

class A {
  x: number;
  y: number;
  z: number;
}

class B extends A {
  value: string;
  flag1: boolean;
  flag2: boolean;
}

Fichier contenant les méthodes de classe A :

class A {
  constructor(x: number, y: number, z: number) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  method1(...) { ... }
  ...
  methodN(...) { ... }
}

Fichier contenant les méthodes de classe 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 de moi. J'aimerais utiliser des modèles tt pour générer des classes Typescript, mais les ajouter dans un fichier séparé qui ne sera pas remplacé par la génération de modèles.

+1 Cela va vraiment m'aider avec mes classes générées automatiquement que je dois étendre

La classe partielle est vraiment sympa mais cela n'a pas de sens de l'avoir. Cela montre que vous avez un problème de conception. La règle de base en programmation est de rester simple et stupide (KISS), quels que soient les langages que vous utilisez, consiste à diviser une grande classe en plus petites - soit en 1) divisant les scripts en classes et en les appelant (d'autres classes peuvent également appeler cela des classes plus petites aussi au lieu de réinventer la roue), ou 2) se séparer et se convertir en Abstrait/Interface/Héritage/Virtuel etc. ou en polymorphisme.

Disons que vous avez un véhicule avec tout dedans. Une classe partielle n'a pas de sens et introduit une complexité et une surcharge ici où il est plus logique de le faire à la place. Créez une classe Engine, une classe Tranny, une classe Drivetrain, une classe Door et une classe Tire en tant que classes séparées et déplacez-y des scripts qui, lorsqu'ils sont appelés, peuvent toujours définir un véhicule dans la classe Vehicle. Il réduit les longs scripts et la complexité des scripts. Il y a de fortes chances que vous trouviez des scripts Door ici et là qui peuvent être simplifiés par une classe Door. Interface/Abstrait/Héritage/Virtuel peut être utilisé pour modifier la définition de la classe Porte sur certains scripts de la classe Véhicule.

Vous êtes également plus susceptible d'avoir moins de temps de développement de cette façon. J'ai eu une fois le blog ASP.NET C# qui utilise beaucoup de classes partielles. J'avais eu du mal avec ça parce qu'il y avait trop de classes partielles et vous ne savez pas où elles se trouvent. C'est un peu comme traiter la logique GOTO en programmation. Mauvais mauvais !! Je n'ai jamais réussi à créer un correctif pour la correction de bogues, ni à personnaliser le script car il était trop enfoui dans une pile de classes partielles (ainsi que certains libellés renommés).

Juste le dire comme une pensée de 1 cent de mon esprit.

@fletchsod-developer : Certaines situations sont correctement gérées par héritage, mais pas toutes. Et certains développeurs peuvent abuser des classes partielles, mais pas toutes. Il y a des situations où je trouve les classes partielles très, très utiles, mais si vous ne les aimez pas, vous n'êtes pas obligé de les utiliser.

@jfrank14 , comme suggéré ci-dessus par @basarat , le #9 ne fonctionnerait-il pas pour vous ?

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

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

@NoelAbrahams , seriez-vous en mesure d'accéder aux définitions du fichier1 dans le fichier mais pas l'inverse ? C'est ok pour moi tant que c'est indépendant de l'ordre d'inclusion.

J'espère vraiment que vous considérez les classes partielles à la C# pour TS... pour moi la seule raison est la génération de code, qui est la principale raison derrière les classes partielles de C#... nous faisons actuellement beaucoup de génération de code TS, et nous attendez-vous à en faire de plus en plus... actuellement, nous devons nous fier à "//

+1 - Pourrait vraiment l'utiliser pour ajouter des fonctionnalités aux classes générées automatiquement ; aucune autre solution élégante n'existe à laquelle je puisse penser ou que j'aie lu à ce jour...

+1 - Classes générées par le code. Objets C#/Java sérialisés vers le client

Besoin de cela également pour la fusion des classes générées !

Ce serait une fonctionnalité très utile pour permettre une fusion simple du code généré avec du code non généré.

+1

+1 - Nous en avons également besoin pour les classes partiellement générées, ce serait plus élégant que l'héritage qui émet pas mal de code qui n'est pas nécessaire à cette fin.

+1

A de nouveau rencontré cette limitation - veuillez ajouter cette fonctionnalité ! :+1:

+1

+1

+1

+1

Les gens +1 au hasard, cela ne va pas le faire avancer.

Les cas d'utilisation à ce jour sont :

  • J'ai de très grandes classes qui s'étendent sur plusieurs fichiers. @RyanCavanaugh a indiqué qu'il s'agissait probablement d'un problème de conception majeur avec un code aussi complexe et insuffisant pour justifier la complexité de la mise en œuvre.
  • Ça leur plaît.
  • Un autre argument semble être C# les a.
  • L'autre argument concerne le code généré à partir d'autres langages.

Les deuxième et troisième cas d'utilisation ne sont pas convaincants et le quatrième, je suppose, nécessite un certain niveau d'explication en quoi la livraison # 9 ne répondrait pas à une exigence très similaire et même aux décorateurs (# 2249).

Il semble que #9 accomplisse la même chose et soit encore plus général (car vous pourriez étendre des classes autres que la vôtre). Mais il pourrait être raisonnable de vouloir le contenu de la classe dans deux fichiers (peut-être parce que l'un est écrit à la main et l'autre généré par un modèle), et de dire que les deux fichiers définissent les membres essentiels de la classe avec une importance égale, et n'exigent pas que l'un fichier "étendre" la classe définie dans l'autre.

C'est une différence presque existentielle, mais peut-être importante pour certaines personnes dans certaines situations.

Je ne veux pas de partialité sur les classes pour les raisons indiquées, mais sur les modules, cela a du sens à mon humble avis.

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

Les classes partielles sont extrêmement utiles pour spécialiser les cas d'utilisation. Il ne s'agit pas d'une violation d'un modèle de POO, mais d'un moyen d'organiser le document de code, qui fournit :

  1. Possibilité de diviser la définition de classe/type en plusieurs fichiers. Pour les fichiers de code volumineux, il s'agit de la fonctionnalité de maintenabilité++.
  2. Possibilité pour le compilateur/système de construction d'utiliser la liaison conditionnelle au moment de la compilation. Analogie MSBuild, cas d'utilisation concret en C# : DBML, classes de concepteur et encore plus de trucs sophistiqués comme https://github.com/dotnet/corefx/pull/2045/files.
  3. Protection inhérente, afin que deux (ou plus) développeurs ne se rencontrent pas lors de l'archivage du code. La résolution des conflits explose ! :)
  4. Laissez-vous générer du code dans la classe partielle principale, puis créez un autre partiel pour les surcharges personnalisées. Fonctionne parfaitement!

Je crois en la séparation de la logique métier et des couches de données en classes distinctes et j'utilise principalement des méthodes statiques dans ces couches. Je ne vois vraiment pas comment cela pourrait être plus de code et moins maintenable.

Alors que la méthode d'extension est une fonctionnalité de base du langage influencée par les modèles OO et sera traitée au moment de la compilation, les classes partielles traitent de la mise en page du document/code à assembler au stade de la pré-compilation. Malgré les similitudes entre les classes partielles, les classes abstraites et les méthodes d'extension, il existe une distinction claire.

:+1: pour avoir apporté les "Classes partielles" inoffensives à TypeScript.

Mon cas d'utilisation pour les classes partielles concerne la génération de code - mon équipe doit être en mesure de générer automatiquement une partie de la classe dans un fichier et d'ajouter des méthodes et des propriétés personnalisées à la main dans un autre fichier. Je ne comprends pas pourquoi @RyanCavanaugh n'est "pas sûr que ce genre de situations s'applique à JavaScript/TypeScript", car ce cas d'utilisation n'est pas lié au langage de choix.

Ni les décorateurs ni les méthodes d'extension ne résolvent le problème de génération de code aussi élégamment que les classes partielles, et chacun présente des complexités supplémentaires substantielles.

+1

+1

+1 à des fins de génération de code.

Dans l'environnement C#, l'intégration d'un transpileur de classes C# aux classes TypeScript supprimerait la nécessité de conserver deux définitions différentes de classes entre le côté serveur et client car le côté client, alias la classe TypeScript, serait automatiquement généré et la classe partielle que ce problème demande permettrait une personnalisation si nécessaire tout en continuant à développer en TypeScript natif.

+1 pour les scénarios de génération de code

+1 extrêmement utile pour la génération de code

Pourquoi ne pas utiliser l'héritage pour la génération de code ?

L'héritage est plus désordonné et a plus de frais généraux.

Le lundi 10 août 2015, à 10 h 09, Gorgi Kosev [email protected] a écrit :

Pourquoi ne pas utiliser l'héritage pour la génération de code ?

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment -129468291
.

L'héritage crée des couplages de noms inutiles

L'héritage est moins impressionnant car il :

  1. Approfondit inutilement la chaîne de prototypes et ralentit l'instanciation,
    bien que ce ne soit pas un gros problème pour la plupart des applications, probablement tout sauf les jeux ;
  2. Par manque d'abstrait et d'override soit perd une certaine sécurité de type ou
    introduit le besoin de certains modèles difficiles comme le lancer entre les deux
    les types;
  3. Est globalement déroutant car avoir une classe de base communique l'idée que
    il peut être étendu par d'autres classes, ce qui est rarement le cas avec codegen

Ne pas dire que le script DOIT avoir des classes partielles pour prendre en charge le codegen, seulement
que les classes partielles sont tellement meilleures que l'héritage ou
composition.

@JoshMcCullough La surcharge d'héritage dans JS est minime, et je ne vois pas en quoi c'est plus compliqué que les classes partielles: avec celles-ci, vous pouvez potentiellement diviser une classe en 10 fichiers et chasser vos méthodes partout.

@yahiko00 De quel genre de "couplage de noms inutiles" parlons-nous ici ? Faites-vous référence aux choses que vous devez faire pour obtenir le n ° 2 ci-dessous (coder en dur le nom de la classe étendue) ?

@hdachev

  1. Il y a des frais généraux, mais c'est assez minime - perceptible uniquement si vous faites des choses qui se traduisent directement par quelques instructions machine
  2. Bon point - vous n'obtenez pas la classe étendue lorsque vous devez référencer la classe générée à partir d'autres classes générées.
  3. Ces classes sont en effet destinées à être étendues - sinon vous pourriez les générer et en finir avec, n'est-ce pas ?

AFAIK, ce n'est pas sur le radar ES7+, n'est-ce pas ? Cela peut poser problème...

Dans tous les cas, attacher des choses supplémentaires au prototype d'une classe existante est assez trivial en JavaScript et pas du tout rare, donc ce pourrait être une bonne idée d'avoir une syntaxe pour ça...

C'est simple dans TS mais le JS dans les coulisses doublerait le
"prototypage" si vous utilisiez des classes de base pour toutes vos données générées
objets. Probablement pas un impact sérieux sur les performances à moins que vous n'ayez une tonne de
objets de données, mais c'est encore inutile quand on sait que "partiellement
cours" sont possibles.

Le lundi 10 août 2015 à 11h03 Gorgi Kosev [email protected]
a écrit:

@JoshMcCullough https://github.com/JoshMcCullough Surcharge d' héritage
dans JS est minime, et je ne vois pas en quoi c'est plus compliqué que les classes partielles :
avec ceux-ci, vous pouvez potentiellement diviser une classe en 10 fichiers et poursuivre votre
méthodes partout.

@yahiko00 https://github.com/yahiko00 Quel genre de "nom inutile
couplage" parlons-nous ici? Faites-vous référence aux choses dont vous auriez besoin
faire pour obtenir le n°2 ci-dessous (coder en dur le nom de la classe étendue) ?

class MyClass étend GeneratedMyClass { ... }

@hdachev https://github.com/hdachev

1.

Il y a des frais généraux, mais c'est assez minime
https://jsperf.com/prototype-chain-vs-direct-calls - seulement perceptible
si vous faites des choses qui se traduisent directement par quelques machines
instructions
2.

Bon point - vous n'obtenez pas le cours prolongé lorsque vous devez
référencer la classe générée à partir d'autres classes générées.
3.

Ces cours sont en effet destinés à être étendus - sinon vous pourriez
les générer et en finir, n'est-ce pas ?

AFAIK, ce n'est pas sur le radar ES7+, n'est-ce pas ?

Dans tous les cas, attacher des choses supplémentaires au prototype d'une classe existante
est assez trivial en JavaScript et pas du tout rare, donc cela pourrait être un
bonne idée d'avoir une syntaxe pour ça...

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/Microsoft/TypeScript/issues/563#issuecomment-129483174
.

@ Davidhanson90 ce fichier ne contient aucune classe. Vouliez-vous poster ceci dans un autre fil?

+1

+1

+100

+1

+1

+1 pour la génération de code.
Je me suis lancé dans angularjs et webapi et je souhaite créer un outil qui crée essentiellement des définitions JS automatiques à partir de mes objets et services c#. Je souhaite ensuite pouvoir étendre ces classes sans avoir à modifier les définitions JS "échafaudées". J'ai vu que quelques autres personnes demandent cela et il semble que nous ayons des cas d'utilisation similaires.

+1 pour la génération de code

+1 pour la génération de code, angular a beaucoup de code passe-partout, nous en faisons déjà beaucoup, mais avec des classes partielles, nous serions capables de faire beaucoup plus.

+1 encore une fois pour la génération de code. Essayer d'étendre les classes dans un autre fichier est au mieux désordonné.

@RyanCavanaugh , que faut-il pour sortir du mode "+1" et aller dans une direction productive ?

-1 une syntaxe suivante est meilleure pour les mixins : #2919

Je ne sais pas pourquoi nous ne pouvons pas avoir à la fois les classes partielles et les mixins ; deux caractéristiques totalement indépendantes.

+1

Ce serait bien lorsque le code est généré, mais vous ne voulez pas le modifier pour ajouter des éléments au code généré.

+1

J'ai une proposition qui devrait satisfaire ces deux cas d'utilisation :

  1. Vous voulez écrire des méthodes de votre propre classe à différents endroits.
  2. Vous souhaitez ajouter de nouvelles méthodes à la classe de quelqu'un d'autre, par exemple une fonction intégrée.

Pour (2), normalement, vous utiliseriez simplement l'opérateur :: pour obtenir la syntaxe infixe.

Mais si vous souhaitez qu'une ancienne classe fasse partie d'une nouvelle interface, ou si vous souhaitez une répartition dynamique, vous devrez réellement modifier le 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 {}
}

(Dans l'exemple, j'utilise des noms de méthode de chaîne, mais comme ce sont des types intégrés, il serait préférable d'utiliser des symboles une fois que ceux-ci peuvent être vérifiés.)

Une amélioration que cela a par rapport aux vraies classes partielles est que la classe a une définition unique, et d'autres endroits l'étendent simplement. Cela signifie qu'il y a un endroit clair pour importer la classe et facilite la traduction vers JS.

:+1: J'aimerais aussi voir des cours partiels.

Quel est le statut de cette fonctionnalité ?

Ce cas d'utilisation par exemple :

J'ai un package Math qui définit une classe Set , avec les méthodes Set#add , 'Set#remove'

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

J'ai un package optionnel , lourd , Relational qui définit les classes Relation et Tuple .

Ce package Relational ajouterait également une méthode Set#product .

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

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

Les cours partiels me permettraient de composer des cours de manière plus flexible. Si je ne veux pas utiliser le package lourd relational , je peux toujours utiliser la fonctionnalité Set de base. D'autres classes partial viendront seulement et ajouteront des fonctionnalités supplémentaires à la classe.

Je me gratte la tête pour faire quelque chose qui aura une belle API sans utiliser de partiels dans ce cas.

Tout ce que je pouvais venir avec, c'est un modèle de référentiel.

// 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 J'utilise t4 pour générer des classes et des proxys sur WebApi. Je pense que l'auto-génération est largement utilisée en tapuscrit et quand il s'agit d'auto-génération, des classes partielles sont nécessaires !

Ce serait génial pour diviser les aspects de la même classe, en particulier dans React
+1

+1 Génération de code et "Juste assez de séparation" dans le cas d'objets de données purement réutilisables avec des attributs spécifiques au client pour une validation similaire qui serait bien d'avoir défini sur la classe mais maintenu dans un morceau de code source séparé.

+1 pour la génération de code des classes partielles et le code manuel des membres supplémentaires pour ces classes dans des fichiers séparés.

+1

+1 J'ai une grande base de méthodes dans notre service js api, il serait préférable de les diviser en fichiers, ce qui facilite la compréhension de chaque méthode.

api comme fb (facebook) ou gq (google analytics) , où vous recevez une classe ou un objet global, que vous pouvez utiliser tout au long de votre développement.

+1

Cette fonctionnalité serait un gros plus pour nous aussi.

Nous avons développé un middleware où tous les types de clients peuvent se connecter et communiquer avec nos serveurs à travers celui-ci.

Nous générons une partie du code client en fonction de ce qui est exposé par les serveurs.

Jusqu'à présent, tout allait bien. Mais maintenant, nous aimerions pouvoir transférer des collections d'objets hétérogènes (mais avec une même classe de base). Les objets transférés font partie du code généré à partir de l'API du serveur.

Pour pouvoir utiliser le pouvoir de l'héritage, les méthodes abstraites sont la clé dans ce cas. Mais nos développeurs n'ajouteront pas de méthodes au code généré, je suppose que tout le monde sait pourquoi ;)

D'après ce que j'ai compris (je suis développeur C#), la solution proposée ici (https://github.com/Microsoft/TypeScript/issues/9) ne nous permettrait pas de le faire.

Donc, des cours partiels seraient parfaits pour nous. Nous générerions la classe comme partielle, et si les développeurs ont besoin d'ajouter de la logique ou des méthodes, ils n'auraient qu'à écrire une autre partie où ils le souhaitent.

+1

+1 très utile pour la génération de code

Je me demande si l'augmentation de module nie fondamentalement la nécessité de cela en tant que fonctionnalité spécifique.

Si vous avez une classe générée, vous devriez pouvoir faire quelque chose comme...

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

@dishishkov Cela semble être un bon moyen de l'implémenter sous le couvert, mais j'aimerais toujours un support de première classe approprié dans le langage sans avoir besoin de modifier manuellement les prototypes et de maintenir cette interface.

Je suis d'accord avec Elephant-Vessel. La partie fabriquée manuellement de la classe partielle doit être aussi faiblement couplée (au moment de la conception dans TS) que possible par rapport à la partie générée.

La suggestion de @david-driscoll fonctionne pour de nombreux cas. Cependant, pour autant que je sache, les prototypes n'ont pas accès aux variables internes. Cela limite l'utilité de cette approche dans les contextes de génération de code où vous souhaitez générer les parties principales de vos classes, puis les augmenter avec du code personnalisé.

+1

@david-driscoll qui semble être un excellent moyen de désactiver cette fonctionnalité. (il faudrait ajouter la possibilité d'accéder à des propriétés privées/protégées). Je me demande ce qui se passerait avec une déclaration de classe partielle multiple ? Quelle serait la visibilité mutuelle de ceux-ci ?

++ 1 Le manque de partiel me fait vraiment mal lorsque j'essaie d'étendre mes modèles générés automatiquement.

Je pense que la seule chose dans la portée ici est essentiellement ce que @david-driscoll a proposé - vous pouvez déclarer de nouvelles méthodes (qui seraient mises sur le prototype) et de nouvelles propriétés _non initialisées_ (qui n'ont pas de codegen), mais pas de nouvelles propriétés initialisées (car ceux-ci ont des effets secondaires sur le codegen constructeur).

downvoted, pardon my french, les classes partielles sont une tentative stupide de fragmenter vos classes divines, qui sont inévitables en POO, en plusieurs fichiers afin qu'elles soient plus faciles à gérer (bien qu'elles soient toujours des classes divines)

avec la POO il n'y a pas d'avenir pour vous les gens (j'y ai été, sachez de quoi je parle)

viens à FP, nous avons des cookies et un moyen d'écrire un programme sans une seule classe et c'est comme ça

Donc, nous l'autorisons déjà de toute façon via interface A { method(): void } A.prototype.method = function() { }; ; codifier cela dans un sucre pour exactement cela a du sens.

Une chose à bikeshed est le mot-clé partial . Une brève vignette historique : en C#, partial class devait à l'origine être extension class (que vous avez mis sur toutes les déclarations sauf une), mais il n'y avait pas de distinction claire sur les déclarations qui seraient les extension et quelle déclaration serait la déclaration de non-extension. A la place, vous avez le modificateur partial que vous devez placer sur _toutes_ les classes.

Ce n'est _pas_ le cas dans TypeScript ; plutôt le contraire. Ici, une seule classe (appelons-la la "déclaration _primary_") peut avoir des constructeurs/champs membres initialisés ; la déclaration primaire n'obtient aucun nouveau modificateur. Toutes les autres déclarations (appelons-les "déclarations _extension_") ne peuvent avoir que des champs statiques, des méthodes et des champs non initialisés, et vous aurez besoin d'avoir un modificateur dessus pour indiquer qu'ils ne sont pas primaires.

La meilleure estimation actuelle est

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

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

:étincelles: :vélo: :maison: :étincelles:

Bikeshedding ou non, cela sonne comme un affreux numéro 311 qui a été abandonné en raison d'une interférence probable avec les futures normes ECMAScript. Pourquoi cela vaut-il la peine d'être pris en compte, mais pas le bon support de mixin ?

L'utilisation du mot-clé extension conflit avec les méthodes d'extension ? Ou est-ce que cela va complètement annuler les méthodes d'extension ?

@kitsonk Je pense que la proposition de mixin a beaucoup plus de questions ouvertes. La proposition de classe partielle ici n'est qu'une codification des choses qui sont déjà autorisées dans TypeScript, juste avec un peu de sucre syntaxique (cette fonctionnalité pourrait littéralement être faite comme un remappage syntaxique à des choses que nous avons déjà).

@Elephant-Vessel Je ne pense pas que des méthodes d'extension se produisent si des classes partielles se produisent. Les classes sont le seul endroit où les méthodes d'extension ont un sens compte tenu de nos contraintes, et l'opérateur de liaison ES7+ proposé est un meilleur moyen de chausse-pied dans une syntaxe de type extension.

@RyanCavanaugh : pour moi, il semble un peu contraignant d'exiger qu'une classe soit primaire et les autres non. Si vous souhaitez partitionner votre code de sorte qu'un fichier contienne toutes les méthodes d'une classe et l'autre toutes les propriétés, aucun des deux ne semble plus manifestement primaire, et pourquoi devriez-vous être obligé de choisir ? N'est-il pas plus propre d'avoir des partiels où ils sont tous de même importance et fusionnés par le compilateur ?

@RyanCavanaugh ... je le ferais exactement de la même manière que c # ... cela fonctionne très bien pour la génération de code ... ce qui, je pense, était le principal problème que la fonctionnalité était censée résoudre en c # ... bien que ma mémoire soit floue ... n'a jamais eu de problèmes, il existe depuis des années et est testé au combat...

Si les classes partielles/étendues ne peuvent pas avoir de champs initialisés, je pense qu'il serait très pratique de prendre en charge quelque chose comme les méthodes partielles que nous connaissons de C# , essentiellement un contrat léger spécifique aux classes partielles. Alors comme :

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

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

Le besoin de pouvoir partialiser/étendre les classes tierces pourrait être assez facilement (?) résolu en rendant le partial/extends généralement facultatif mais requis pour l'utilisation de méthodes partielles.

Je pense que cela pourrait apporter une certaine puissance expressive et opérationnelle au concept que nous voulons ici.

Ceux qui recherchent des mixins.

Considérez la proposition d'initialisation de l'

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

Les langages tels que Java n'offrent pas de classes/structures partielles. C'est une fonctionnalité de niche de C#. Imiter pleinement les concepts de "classe/structure partielle" C# est la meilleure façon de procéder ici.
Lors de l'étape de pré-compilation, la première chose que le compilateur TS pourrait faire est d'assembler les blocs de code partiels en mémoire, puis de passer à la route du pipeline de compilation normale. Ce sera plus que suffisant pour se qualifier pour la fonctionnalité v1.0.0-preview1.0000 de classes partielles dans TypeScript.
Tout ce qui va au-delà de ce que C# propose est quelque chose qui peut être introduit dans les versions ultérieures lorsque la fonctionnalité évoluera et survivra à son essai/préversion. Les cas de coin et le même genre de choses obscures peuvent être discutés séparément un à la fois et nous pouvons nous inquiéter de l'ajustement et de la finition plus tard... IMO.

Je suis également d'accord pour faire à la fois des classes partielles et des classes d'extension exactement comme c#
est-ce la meilleure voie à suivre en termes de syntaxe et de sémantique, les deux fonctionnent
extrêmement bien pour leurs cas d'utilisation respectifs. Les cours partiels améliorent la
l'utilisabilité du code généré. Les méthodes d'extension améliorent la convivialité
de méthodes statiques qui opèrent sur des interfaces, des génériques spécifiés et des tiers
types de fête. Les deux sont vraiment cool, mais n'oubliez pas qu'ils ne sont pas les
même fonctionnalité, je dis cela ici à cause de la syntaxe proposée ci-dessus.

Les méthodes d'extension permettraient de le faire (sry à propos du manque de formatage,
taper sur un téléphone):

étendre MonType[] {
quelque choseSpécifiqueVersMonType() { ... }
}

étendre WeirdThirdPartyDatastructure{
pareil ici() { ... }
}

Cela, entre autres, comme pouvoir utiliser des bibliothèques comme le soulignement
sans le cruft, ce qui signifie essentiellement récolter les avantages syntaxiques de
étendre les types intégrés sans les polluer réellement.

Si bref - ne traitons pas les deux comme une seule et même chose, ils sont tous les deux très
cool mais pas la même chose. J'aimerais personnellement avoir les deux dans notre
Langue.

Soit dit en passant, j'imagine que beaucoup de gens grincent des dents à l'idée de
génération de code et sont prêts à expliquer à tout le monde qu'il n'a pas sa place
en javascript car il existe des moyens plus idiomatiques d'obtenir la même chose.
Il y a deux façons dont la génération de code est d'une grande aide dans certains
projets, comme celui sur lequel je travaille en ce moment.

  • Dans les projets sensibles aux performances, tels que les jeux, où vous
    tout pour maximiser votre budget CPU avec un travail utile, codegen aide énormément
    pour générer un code à la fois simple à raisonner et hautement optimisable
    / code monomorphe qui colle vraiment bien. Par exemple, dans un
    moteur de jeu entité/composant, le code généré peut aider avec une tonne de choses
    comme un code passe-partout très rapide pour coller des composants ensemble, un événement
    expédition, etc
  • Dans les applications des grandes entreprises, le code généré permet d'obtenir un kilométrage extrême de
    le système de types, par exemple en émettant des méthodes avec des
    signatures pour les requêtes de base de données, etc., ce qui maximise le temps de compilation
    vérifie, aide énormément à la refactorisation et simplifie également grandement le débogage
    car il vous permet de parcourir un code d'orchestration très simple.
  • Le plus important, c'est lorsque vous gardez certains composants synchronisés sur
    environnements multilingues, par exemple quelque chose lié à la messagerie
    comme les tampons de protocole, ou simplement les interfaces de message json, etc.

En tant qu'autre nœud latéral au profit de tous ceux qui se demandent quelle partie
les classes ont à voir avec codegen, la valeur de conserver les parties générées
d'une classe dans un fichier séparé provient des exigences de contrôle de source -
les éléments générés sont généralement un artefact de construction en évolution rapide et vous
ne voulez pas qu'il soit engagé dans votre repo.

J'aime l'idée d'implémenter cela en fonction d'un modèle bien connu et éprouvé de ce concept, tout comme ce que C# a. « Imitation » a des connotations négatives, mais elle a une valeur significative si elle est faite intelligemment. D'un autre côté, la partie "intelligente" de cela est d'être conscient des différentes circonstances et limitations, donc je ne protesterai pas si les partiels pour TypeScript ne ressemblent pas exactement aux partiels pour C#.

@Elephant-Vessel, je suis d'accord qu'il n'est pas nécessaire que ce soit une copie idem des partiels C#, la conception générale peut d'abord être conçue autour de la saveur TypeScript / JavaScript tout en s'inspirant au maximum des partiels C#. Ma suggestion est d'utiliser le « mot-clé d'enregistrement partial » et « l'assemblage de partiels » dans un premier temps, et de l'envoyer en tant que fonctionnalité expérimentale/d'aperçu (afin que le consommateur ne commence pas à en dépendre dans le code de production correctement d'emblée). Plus tard, en fonction de la réponse de la communauté, faites évoluer la fonctionnalité jusqu'à ce qu'elle soit prête pour la production et RTM. Si nous nous inquiétons à l'avance de toutes sortes de pièges et de scénarios délicats, cela retardera très probablement la question.

+1 - Pour étendre et maintenir les objets générés.

+1 pour maintenir le code généré

J'ai créé polyfill et divisé ma grande classe.

Définir une classe comme interface.

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

Mettre en œuvre les membres de la classe.

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

Fusionner les implémentations.

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

Je pense que c'est une idée terrible pour une raison spécifique: cela aggravera considérablement les règles déjà compliquées pour les problèmes d'héritage dépendant de l'ordre de déclaration global, ambiant, externe, espace de noms et fragile. Ce n'est pas C# et la résolution de noms et les déclarations de membres sont très différentes.

Utilisez peut-être un objet ou un espace de noms au lieu d'une classe, à la manière du modèle de module révélateur si vous en avez vraiment besoin. Sinon, votre classe est probablement trop grande.

Les décorateurs peuvent également être utilisés pour implémenter des associations entre le code généré et le code écrit à la main.

Avez-vous d'autres solutions ?

J'aimerais voir cela ajouté à TS aussi

+1 à des fins de génération de code (DTO d'une référence de service WCF avec des définitions de classe partielles supplémentaires)

+1 à des fins de génération de code. Mon cas d'utilisation est le suivant : j'ai des composants React dont les fonctions render() sont générées en externe via des react-templates .

Avec les classes partial , je pouvais vérifier le type de ces fonctions par rapport à la classe principale (la Component ). Sans classes partielles, la seule chose que je puisse faire est de lier la fonction à la classe principale et d'espérer le meilleur.

Avec le prochain TS 2.0, je pensais que certains cas de génération de code pourraient être couverts par la fonctionnalité de type this .

Par exemple dans le cas que j'ai décrit précédemment, au lieu de

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

je peux écrire

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

+1 En tant que développeur, je veux des classes partielles afin que plusieurs modèles puissent générer/modifier la même classe répartie sur plusieurs fichiers.

Mes commentaires concernaient spécifiquement les classes partielles, pas les mixins. Les deux sont fondamentalement différents. Les classes partielles consistent à décomposer le code physique, les mixins consistent à décomposer le comportement logique en traits réutilisables enrichissant d'autres objets à la fois au niveau du type et de la valeur.
Je ne pense pas que les classes partielles soient une bonne idée pour TypeScript. Les mixins, en revanche, sont une bonne idée, offrant une expressivité accrue et un maillage extrêmement bien avec le système de types de TypeScript et les idiomes JavaScript, comme l'a souligné @aleksey-bykov

@wendellm pouvez-vous penser à un moyen propre de le faire étant donné que les modules ES sont physiques. Les classes partielles fonctionnent bien et ont beaucoup de sens dans un langage comme C# où les modules sont logiques et non physiques. Du point de vue du CLR, les espaces de noms n'existent pas, c'est juste que les noms de classes peuvent contenir des points (source une interview avec @ahejlsberg)

+1 J'ai besoin d'un cours partiel !

pouvons-nous extension interface? interface peut également avoir des fonctions implémentées, tout comme Swift :

interface Rect {
    x: number
    y: number
}

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

Version rapide :

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

+1

La génération de code et les classes partielles vont de pair.

L'héritage est une mauvaise solution à ce qui est essentiellement une directive glorifiée #include .

Prenez Angular 2 par exemple. Il ne lira pas les métadonnées de la classe parent, ce qui rend l'extension par héritage peu pratique.

@tsvetomir c'est un problème Angular pas un problème TypeScript.

L'héritage est une mauvaise solution à ce qui est essentiellement une directive #include glorifiée

Oui, l'héritage est une mauvaise solution, mais le problème est d'utiliser les classes en premier lieu. Ils ont leur place mais elle est très limitée. Les classes JavaScript sont assez faibles et inexpressives par rapport aux classes d'autres langages.

Le tapuscrit n'est pas un langage "angulaire"... n'a jamais été

Le 23 juillet 2016, à 21h46, Aluan Haddad < [email protected] [email protected] > a écrit :

@tsvet omirhttps://github.com/tsvetomir c'est un problème Angular pas un problème TypeScript.

L'héritage est une mauvaise solution à ce qui est essentiellement une directive #include glorifiée

Oui, l'héritage est une mauvaise solution, mais le problème est d'utiliser les classes en premier lieu. Ils ont leur place mais elle est très limitée. Les classes JavaScript sont assez faibles et inexpressives par rapport aux classes d'autres langages.

Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, affichez-le sur Gi tHubhttps://github.com/Microsoft/TypeScript/issues/563#issuecomment -234753589, ou coupez le son de la

Je ne vois en aucun cas le problème comme spécifique à Angular. C'est un cas particulier dans lequel des cours partiels ont pu aider.

La demande provient de l'expérience passée avec C# et du manque de fonctionnalités familières. La comparaison est inévitable car TypeScript ne fait aucun effort pour se distancier de .NET. Une certaine forme de parité des fonctionnalités est attendue par ses utilisateurs.

La demande provient de l'expérience passée avec C# et du manque de fonctionnalités familières. La comparaison est inévitable car TypeScript ne fait aucun effort pour se distancier de .NET. Une certaine forme de parité des fonctionnalités est attendue par ses utilisateurs.

@tsvetomir en tant que développeur .NET de longue date et en tant que programmeur C# passionné, je suis fondamentalement en désaccord.

L'article que vous avez cité ne fait pas autorité et ne reflète aucun document officiel de l'équipe TypeScript.

De plus, cela contredit directement la philosophie de conception de TypeScript telle qu'énoncée par @ahejlsberg dans de nombreux entretiens, interviews et publications.

De plus, le point de vue de l'article cité reflète un malentendu fondamental quant à la nature de TypeScript.
Ironiquement, les points communs que C# a avec TypeScript sont en fait les mêmes qu'il a avec JavaScript.
Ces points communs ne sont pas une programmation basée sur les classes, mais plutôt des constructions telles que des fermetures et des fonctions d'ordre supérieur.

C# ou non, nous avons besoin de classes partielles qui aideront TypeScript à se rapprocher des fonctionnalités du prototype de Javascript.

@yahiko00
TypeScript possède déjà toutes les fonctionnalités de prototype de JavaScript.
C'est un sur-ensemble.

Il y a plusieurs problèmes avec la notion de classes partielles dans TypeScript, y compris

  1. Contrairement à C#, les définitions de classe TypeScript (JavaScript) sont impératives et non déclaratives. Ils semblent déclaratifs, mais ils ne le sont pas. Cela signifie qu'ils dépendent d'un ordre d'exécution déterministe.
  2. Le système de module ECMAScript est basé sur l'importation d'unités de code physiques et non logiques.
    Par exemple, disons que j'ai

_app/my-class-part-1.ts_

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

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

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

Comment importer cette classe ? Puisque je ne peux pas importer depuis l'un ou l'autre module, imaginons une abstraction hypothétique dans TypeScript qui me permet d'écrire
_app/main.ts_

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

Qu'est-ce que cela signifierait? Même si le compilateur TypeScript pouvait déduire que _app/my-class-part-1.ts_ doit être chargé avant _app/my-class-part-2.ts_, il ne peut pas invalider l'importation des parties individuelles ni garantir ils sont importés dans le bon ordre par un chargeur de module asynchrone tel que RequireJS ou ce qui sera éventuellement implémenté dans les navigateurs.

Toute la notion de classes partielles est fondamentalement en contradiction avec le système de modules ECMAScript.

Mise à jour : il faudrait effectuer une inférence de dépendances arbitrairement complexe et émettre du JavaScript très étrange.

TypeScript possède déjà toutes les fonctionnalités de prototype de JavaScript.
C'est un sur-ensemble.

J'aurais dû mieux m'exprimer. Bien sûr, nous savons tous que TypeScript est un sur-ensemble de JavaScript. Mais je voulais dire que les classes partielles aideraient les classes TypeScript à se rapprocher des prototypes JS. Pour le moment, on peut juste avoir des classes "statiques" et non extensibles, alors qu'avec une approche prototype, on peut étendre des fonctions de type classe.

L'importation de classes partielles conduirait à étendre la syntaxe ES6 actuelle, je suis d'accord. On pourrait imaginer quelque chose comme ça :

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

Les classes TypeScript sont basées sur les classes ECMAScript et souffrent donc du manque d'expressivité de ces dernières. Pensez à utiliser des fonctions, des modules, des "espaces de noms" ou des objets simples pour accomplir ce dont vous avez besoin.

Les fonctions sont ce que nous voulons éviter avec la notion de classe.
Les modules ou les espaces de noms apportent une extensibilité simple et n'ont pas la même expressivité que les classes de TypeScript. De plus, un espace de noms ou un module ne peut pas être instancié. Ils n'ont pas le même objectif que les cours.

@aluanhaddad Je vois ce que vous voulez dire concernant les modules. Une solution possible serait de n'autoriser qu'un seul des fichiers à export partial class tandis que les autres ne contiennent que des définitions de partial class . Vous l'importez de l'endroit où il est exporté. D'après ton exemple :

_app/ma-classe.ts_

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

_app/ma-classe.part.ts_

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

_app/main.ts_

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

Ce qui manque, c'est une syntaxe pour indiquer au compilateur où localiser les pièces. Ce n'est pas un problème avec C# où vous traitez tous les fichiers à la fois. Il peut s'agir d'une syntaxe spéciale, comme celle utilisée pour la fusion des déclarations .

Il n'est pas nécessaire que les classes partielles autorisent des définitions arbitraires. Ils peuvent être limités uniquement aux méthodes, propriétés et constructeurs, par exemple. Cela rend l'ordre d'exécution insignifiant et permet au compilateur de générer une erreur si un membre est dupliqué.

Je ne vois pas pourquoi Module Augmentation n'est pas valable pour ces scénarios. Cela a très bien fonctionné pour nous avec Rxjs5.

Vous créez simplement votre classe de base, puis avec votre génération de code, générez toutes les méthodes augmentées dont vous avez besoin en plus de la classe de base. Peu importe que le code généré soit joli, aucun humain n'est censé l'écrire.

Est-ce un remplacement parfait pour les cours partiels? Je suppose que non, mais je ne vois pas de classes partielles se produire à moins qu'ECMAScript ne décide que JavaScript en a besoin. La sémantique de la façon dont les classes partielles sont liées entre elles entre des modules externes me fait mal à la tête.

@david-driscoll pour le rendre encore meilleur, les méthodes ajoutées peuvent avoir un argument this: déclaré, pour une vérification de type plus forte.

Dans l'exemple cité de 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
}

Oui. Rxjs ne l'utilise pas encore, car c'est une fonctionnalité 2.0, et la 2.0 n'est pas encore sortie. C'est sur ma liste de succès plus tard.

Je vois ce que tu veux dire concernant les modules. Une solution possible serait de n'autoriser qu'un seul des fichiers à exporter une classe partielle tandis que les autres ne contiennent que des définitions de classe partielles. Vous l'importez de l'endroit où il est exporté. D'après ton exemple :

_app/ma-classe.ts_

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

app/ma-classe.part.ts

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

J'aime le concept syntaxique mais le problème est que vous venez d'introduire un nouveau _type_ de fichier source qui est consommé comme une sorte de module implicite, ressemble à un script et doit être chargé d'une manière spécifique.

Ce qui manque, c'est une syntaxe pour indiquer au compilateur où localiser les pièces. Ce n'est pas un problème avec C# où vous traitez tous les fichiers à la fois. Il peut s'agir d'une syntaxe spéciale, comme celle utilisée pour la fusion des déclarations.

La fusion des déclarations fonctionne pour les _déclarations_, pas pour les fichiers source.

Il n'est pas nécessaire que les classes partielles autorisent des définitions arbitraires. Ils peuvent être limités uniquement aux méthodes, propriétés et constructeurs, par exemple. Cela rend l'ordre d'exécution insignifiant et permet au compilateur de générer une erreur si un membre est dupliqué.

Tous ces éléments sont généralement dépendants de l'ordre.

Edit : C'est-à-dire que les définir modifie la classe.

Quelqu'un l'a probablement déjà mentionné, mais un autre cas utile est celui où vous générez une partie de la classe à partir d'un générateur de code, puis vous souhaitez ajouter manuellement du code supplémentaire directement dans votre implémentation.
Vous ne souhaitez pas vraiment faire de mixage ou de classe dérivée.
C'est toujours une classe - une partie est générée automatiquement, une autre partie manuellement.

BTW : si quelqu'un a besoin de générer des types TS à partir de classes C#, vous pouvez vérifier TypeScriptBuilder

Merci d'avoir pensé à ça !

Je vais essayer votre TypeScriptBuilder ;)

Ma suggestion...

Et si le compilateur n'essayait pas de trouver toutes les pièces ? Et si je devais importer d'autres pièces et tout contrôler ?

/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;
    }
}

Puis...

  1. Si je veux utiliser MyClass je dois l'importer depuis MyClass.ts
  2. Une fois compilé, MyClass.partial.ts générera un javascript qui étend MyClass.prototype comme montré ici auparavant. Mais il exporte une fonction qui reçoit le prototype à étendre.
  3. MyClass.partial.ts est importé dans MyClass après que MyClass a été défini et sa fonction d'extension est appelée.

En passant... rien ne m'empêche de générer directement le code compilé. Mais je perds toute la grandeur de Typescript.

@svallory Je pense que c'est certainement la bonne approche ici. Plus précisément, parce que vous dites que le code généré exportera une fonction qui provoquerait l'augmentation, cela fonctionnerait même avec des importations asynchrones car les fonctions peuvent être appelées dans l'ordre déterministe nécessaire.

Plus généralement, et j'oublie le problème où il était référencé, si les affectations au prototype de classe affectaient la forme de la classe, il pourrait y avoir de nombreux avantages. Cela améliorerait les bibliothèques mixin, rendrait les décorateurs beaucoup plus utiles et encouragerait généralement les hiérarchies moins verticales.

Il pourrait être difficile pour le compilateur de suivre tout cela, mais cela pourrait probablement fonctionner en étant explicite comme vous le suggérez.

Il s'agirait d'une amélioration du système de types, le cas d'utilisation des classes partielles sortant de cette amélioration.

Je l'ai fait comme suit :

Je l'ai fait comme suit :
 fichier1 . ts
 interface ifoo {
 a ( ) : nul ;
 }
 la classe foo implémente ifoo {
 a ( ) { /*faire quelque chose*/ }
 }
 fichier2 . ts
 /// <chemin de référence="file1.ts" /> //pas nécessaire
 interface ifoo {
 b ( ) : nul ;
 }
 foo . proto . b = ( ) = > { /*faire quelque chose*/ }
 fichier3 . ts
 /// <chemin de référence="file1.ts" /> //pas nécessaire
 interface ifoo {
 c ( ) : nul ;
 }
 ( < ifoo > foo . prototype ) . c = ( ) = > { /*faire quelque chose*/ }
 consommateur . ts
 /// <chemin de référence="file1.ts" />
 /// <chemin de référence="file2.ts" />
 /// <chemin de référence="file3.ts" />
 let f = new foo ( ) ;
 f . un ( ) ;
 f . b ( ) ;
 f . c ( ) ;

L'augmentation de module résout toujours 90% du problème ici. Compte tenu des exemples de

/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;
    }
}

L'augmentation du module serait quelque chose comme...

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

C'est un peu plus détaillé qu'une classe partielle, mais en réalité, la classe partielle ne serait que du sucre syntaxique pour cette implémentation.

Les seuls pièges que vous n'avez pas aujourd'hui seraient :

  • Vous ne pouvez pas accéder aux champs privés ou protégés en utilisant la syntaxe this: MyClass .

    • Cela peut être facilement résolu dans le code généré en transtypant en any .

    • C'est peut-être quelque chose qui peut être ajouté, de sorte que vous puissiez accéder aux membres protégés de this . Il peut y avoir d'autres règles à ce sujet.

  • Le code généré semble un peu plus intimidant, mais pour le consommateur, une fois les choses augmentées, il ne saura jamais faire la différence.

EDIT : gardez à l'esprit qu'il s'agit de la syntaxe TS 2.0+.

@david-driscoll Je suis d'accord. Je pense que c'est plus simple et j'aime que cela n'introduise pas la syntaxe supplémentaire. Comme vous le savez, je suis opposé aux classes partielles en tant que fonctionnalité de langage spécifique, mais je pense qu'il serait avantageux que TypeScript suive les affectations aux prototypes en général et affine la forme de l'objet en conséquence. Je pense que votre approche est la bonne façon de diviser les classes sur plusieurs fichiers.

@wongchichong Votre exemple utilise des noms de classe globaux et /// <reference path="..."/> . Je ne pense pas que cela évoluera bien, bien que vous puissiez utiliser un espace de noms pour améliorer la situation.
Le code écrit en tant que modules (c'est-à-dire des modules externes) est une bête très différente car il implique un chargeur qui doit être conscient des dépendances qui dépendent de l'ordre et sont implicites. C'est pourquoi la suggestion de @svallory est précieuse, elle nécessite une quantité très minimale de câblage manuel qui rend les dépendances explicites.

Que faire si quelqu'un n'utilise pas de modules ?

Les cours partiels

Pour clarifier, je veux dire qu'ils sont une mauvaise idée dans un langage comme JavaScript où les déclarations de classe sont impératives, pas déclaratives. Même si vous utilisez des espaces de noms, vous finirez par diviser votre code en plusieurs fichiers, ce qui signifie que vous devrez dépendre de l'ordre des balises de script de ces fichiers pour que cela fonctionne.

Dans un langage comme C#, les classes partielles fonctionnent bien mais c'est parce qu'elles sont fondamentalement différentes des classes en JavaScript.

Il est important de se rappeler qu'en JavaScript, les déclarations de classe ne sont même pas historiées et encore moins déclaratives.

Hors ES6, le concept de "classe" est défini par TS. JS n'a aucune notion de classe _du tout_.
C'est donc à TypeScript de décider ce qu'une classe peut être, non ?

Sauf ES6,

Nous ne pouvons pas interdire ES6 lorsque nous discutons des fonctionnalités du langage TS, car l'un des objectifs de TS est de suivre les spécifications ES actuelles/futures .

Vrai que :/

Pour les grands systèmes avec des classes générées par le code, c'est-à-dire les entités, les clients de la couche de service, etc., les classes partielles selon la conception C#, fournissent une solution très élégante lorsque le code généré doit être étendu avec un état et un comportement supplémentaires. Sur mon projet actuel, où nous avons environ 500 classes de génération de code, cette fonctionnalité me manque beaucoup.

Je ne comprends toujours pas pourquoi certaines personnes sont si hostiles à une fonctionnalité qui s'est avérée utile ailleurs, sauf à dire "c'est une mauvaise idée".

Il semble que cela n'ait pas été beaucoup discuté sur esdiscuss, le seul fil que j'ai trouvé a 9 messages.

@yahiko00 Ce n'est pas que je sois hostile au concept. Comme vous le dites, il est très utile dans des langages tels que C#.

En tant que programmeur C# enthousiaste, je trouve que les classes partielles sont très utiles pour certaines tâches. Cependant, ils n'interfèrent pas avec les autres aspects de la langue. Ils ne cassent pas les abstractions liées aux clés telles que les espaces de noms, les assemblys et les déclarations de type arbitrairement ordonnées.

JavaScript, d'autre part, a un système de modules qui est au mieux naissant. Les classes sont une caractéristique nouvelle et, je dirais, pas encore très expressive de la langue, elles ont besoin de temps pour se développer.

Si nous prenons un peu de recul et considérons les méthodes d'extension, une autre fonctionnalité puissante et bien plus utile de C#, j'aimerais les voir ajoutées à JavaScript, mais il existe des problèmes fondamentaux à ce sujet qui n'ont pas encore été résolus.

Lorsque nous atteindrons un point où des classes partielles peuvent être spécifiées sans casser ou restreindre sévèrement des concepts beaucoup plus fondamentaux tels que les modules, je serai tout à fait favorable à leur ajout.

Cela dit, comme le souligne @SaschaNaz , cela _doit_ être traité dans ECMAScript.

Peut-être que toute personne intéressée peut ouvrir un nouveau fil sur http://esdiscuss.org et poster l'URL ici afin que nous puissions continuer la discussion là-bas 😄

PS: Ou sur un discours ES plus GitHub-like .
PS2 : Ou sur WICG aussi-like-GitHub-et-plus-

Moi aussi, j'aimerais voir une construction permettant la génération de code pour TS. Les classes partielles fonctionnent très bien pour cela en C#.

Il me manque peut-être quelque chose, mais il me semble que le problème principal est d'étendre une classe avec un accès à des variables "privées" à partir d'un autre endroit que dans le constructeur, de préférence à partir d'un autre fichier.

Sur la base de la discussion, il semble qu'une grande partie de l'innovation TS « sûre » a été réalisée. Maintenant, nous attendons juste de voir ce que fait l'organe de gouvernance des SE parce que nous ne voulons rien casser à l'avenir. Tout à fait valable, mais un peu décourageant car j'espérais un train plus rapide avec TS.

Un prérequis est de trouver un bon désucrage :

Bien que je pensais auparavant que les classes partielles étaient assez idiotes parce que vous pouviez simplement ajouter à la classe directement, je peux voir l'attrait étant donné que cela impliquera de rendre vos méthodes non énumérables et de corriger la super liaison (cette dernière est actuellement impossible dans ES6).

Nous devons d'abord trouver un bon désguar pour les classes en général en primitives compositionnelles impératives, comme l'ancienne toMethod. Mais une fois que nous avons cela, ajouter un peu plus de sucre sur le dessus comme des classes partielles peut être raisonnable, selon l'ergonomie --- ou non --- ces primitives finissent par être.

Je ne sais pas ce que cela signifie exactement, mais probablement comme ceci :

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

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

(Croix publiée sur esdiscuss )

Il semble qu'il existe un moyen assez simple d'implémenter une classe partielle en JS pur (avec ES2017 getOwnPropertyDescriptors ). Les personnes ES peuvent penser qu'une syntaxe sucrée ne sera même pas nécessaire uniquement pour supprimer ce petit 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;
}

L'utiliser sur TS nécessite un doublon de interface pour étendre le type de classe existant, bien sûr.

@SaschaNaz Je m'attends à ce que les propriétés ajoutées au constructeur via getOwnPropertyDescriptors soient masquées pour l'"autosuggestion" IDE (puisqu'elles sont ajoutées au moment de l'exécution). Rappelez-vous, Typescript est né comme JavaScript avec "autosuggestion" (parfois les gens l'appellent "stronlgy typé", mais ce qu'ils aiment vraiment, c'est "autosuggestion").

PS Pourquoi les gens ont besoin de classes partielles - génération de code. Mais encore une fois, la génération de code devrait être prise en charge à la fois par l'IDE (un "outil" facile à ajuster au fichier source, résultat hiérarchique dans l'explorateur de fichiers, T4 ou support similaire du "générateur de code commun") et par le langage (classes partielles, méthodes d'extension). Ce n'est qu'après avoir compris cela qu'il est possible de comprendre ce que les développeurs demandent vraiment. Si vous ne voyez pas l'image complète - bien sûr, les "classes partielles" ressemblent à des "absurdités".

@aluanhaddad : mais la fonction principale de TypeScript n'est-elle pas de nous fournir des éléments de langage qui ne sont pas présents dans JavaScript ? Pourquoi est-ce une mauvaise idée d'avoir une classe divisée en deux fichiers TypeScript partiels, qui seront compilés en un seul fichier JavaScript ?

Je ne vois vraiment pas le problème de donner un outil à la communauté. Et je suis sûr à 100% qu'il y aura des développeurs qui en abuseront. Mais aussi des développeurs qui savent exactement comment l'utiliser. Mais n'avons-nous pas la même situation avec n'importe quelle construction de n'importe quelle langue ?

+1 à des fins de génération de code. Et je suis d'accord avec @rpokrovskij , pourquoi nous choisissons TypeScript, je peux également utiliser JavsScript directement, simplement parce que cela ressemble à C# et prend en charge ide.

@greendimka Je ne sais pas comment cela pourrait fonctionner sans à la fois diverger et ajouter à la complexité substantielle des modules ES.

@xiexin36 TypeScript
Il existe des points communs entre JavaScript et C#, mais leurs notions de class sont des mondes à part.

@ xiexin36 pour la génération de code, vous pouvez toujours utiliser l'augmentation de module (comme je l'ai noté plus tôt dans ce fil ). Syntaxiquement, ce n'est pas aussi "facile" que les classes partielles, mais vous pouvez accomplir la même tâche.

@aluanhaddad Eh bien, cela fonctionne très simplement : les classes partielles ne modifient en aucune manière la structure du code. Ils nous permettent juste d'écrire la définition de la même classe dans plusieurs fichiers (qui sont de toute façon compilés en un seul JS).

@aluanhaddad À proprement parler : javascript n'a pas de concept de classes (les classes ES6 fournissent juste un sucre syntaxique). Donc, si nous essayons de suivre le concept d'avoir TypeScript aussi faible que JavaScript - ne devrions-nous pas jeter les classes de TypeScript ? Ne devrions-nous pas simplement revenir à JavaScript ?

Les classes
TypeScript ne vise pas à ajouter des constructions supplémentaires au runtime de JavaScript.

Les classes ES6 sont _très_ ternes. Cela ne veut pas dire que JavaScript n'est pas un langage puissant (il l'est). TypeScript fournit un typage statique pour détecter les erreurs au moment de la conception, fournit des outils de haute qualité, permet une spécification extrêmement précise et rigoureuse des interfaces de composants et améliore généralement la productivité.

Les classes ES6 sont _très_ ternes, mais pour TypeScript, introduire sa propre notion de classes serait en violation directe de ses objectifs de conception.

Évitez simplement les cours et votre problème sera résolu.

Eh bien, cela fonctionne très simplement : les classes partielles ne modifient en aucune manière la structure du code. Ils nous permettent juste d'écrire la définition de la même classe dans plusieurs fichiers (qui sont de toute façon compilés en un seul JS).

Et casser presque tous les outils connus de l'homme ? Non, merci.

@david-driscoll Merci, je vais l'essayer, mais j'utilise aussi Angular 2.0, je me demande si je génère du code avec
@Input ou @Output , ça fonctionnera, de toute façon je vais l'essayer.

@aluanhaddad c'est

Et au fait, l'équipe TypeScript, donnez-nous aussi des fonctions partielles ! Et s'il vous plaît dites la même chose à l'équipe C#, puisque nous avons là des "fonctions dans les fonctions" pour l'instant. :)

Juste pour être sûr, vous vous rendez compte que les fonctions partielles ont une signification très spécifique et que ce que vous décrivez ne sont pas des fonctions partielles par un effort d'imagination ?
La génération de code est utile, je l'utilise aussi.

@aluanhaddad . Comprenez-vous le terme "une unité de compilation dans plusieurs fichiers" ? Javascript n'est bien sûr pas un langage de compilation mais a) la fonction doit être entièrement analysée avant l'exécution et nous pouvons nommer cette "compilation" b) Typescript est un langage de compilation.

Pour aider votre imagination :

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

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

Je n'utilise pas non plus souvent les classes partielles : pour les utiliser efficacement nous devons stocker les paramètres de génération de code dans la partie "manuelle" et pour lire cette configuration nous devons avoir un bon parseur de langage (pas de réflexion). Mais c'est comme ça : les classes partielles ne sont qu'un instrument parmi tant d'autres pour rendre la génération de code confortable.

@rpokrovskij
Je m'excuse si je suis devenu hostile. Je ne voulais pas offenser ou manquer de respect.

Votre exemple comporte des aspects qui nécessiteraient une description assez formelle à part entière. Cette proposition ne visait pas à l'origine à activer directement des scénarios de génération de code.

@aluanhaddad....
"Évitez simplement les cours et votre problème sera résolu" - sérieusement, c'est une solution à un problème ?! Probablement si j'évite d'utiliser JavaScript - je peux résoudre le problème de toute cette discussion. Une solution aussi, n'est-ce pas ? Malheureusement, nous avons ce langage de merde dans notre univers car il a eu la chance de se lancer sur le Web il y a de nombreuses années. Quoi qu'il en soit, c'est un hors-sujet.

"casser presque tous les outils connus de l'homme" - comment est-ce possible ??? Comment?!?! J'essaie d'imaginer casser quelque chose en utilisant des classes partielles dans TypeScript, mais je ne peux pas. Je ne peux tout simplement pas. S'il vous plaît, aidez-moi ici avec un exemple réel.

Imaginez maintenant que vous avez construit une voiture pour transporter des cartons. Cela fonctionne sans aucun problème. Vous engagez un ouvrier, qui charge la voiture. Le travailleur prend deux boîtes à la fois et les met dans la voiture. Pourtant tout fonctionne bien.
Un jour, le travailleur part pour une autre entreprise et vous en embauchez une nouvelle. Le nouveau prend une seule boîte, la charge, prend une autre seule boîte et la charge également. Logiquement : tout va bien. Mais vous courez partout et criez : arrêtez, arrêtez, nous avons une panne système ! :)

"Évitez simplement les cours et votre problème sera résolu" - sérieusement, c'est une solution à un problème ?! Probablement si j'évite d'utiliser JavaScript - je peux résoudre le problème de toute cette discussion. Une solution aussi, n'est-ce pas ? Malheureusement, nous avons ce langage de merde dans notre univers car il a eu la chance de se lancer sur le Web il y a de nombreuses années. Quoi qu'il en soit, c'est un hors-sujet.

ES2015 a certainement beaucoup de problèmes. ES5.1 avait certainement beaucoup de problèmes. À mon avis, le manque de cours n'était pas une de ces choses. Mon point est qu'en utilisant des techniques telles que le modèle de module révélateur, vous évitez le besoin de classes partielles. TypeScript fournit du sucre pour le modèle de module révélateur, les espaces de noms.

"casser presque tous les outils connus de l'homme" - comment est-ce possible ??? Comment?!?! J'essaie d'imaginer casser quelque chose en utilisant des classes partielles dans TypeScript, mais je ne peux pas. Je ne peux tout simplement pas. S'il vous plaît, aidez-moi ici avec un exemple réel.

Si vous utilisez des modules ES, cela pose problème. Tout outil qui repose sur les artefacts physiques du compilateur ayant une correspondance avec leurs homologues non compilés serait soumis à cela. Cela dit, TypeScript pourrait s'adapter à cela dans l'émission, un changement massif, mais il émettrait alors du JavaScript qui ne correspondrait pas au TypeScript que vous avez écrit.

Donc, au fond, l'évolution d'un langage est freinée par les outils, qui n'évolueront jamais sans l'évolution du langage.
Désolé, mais je ne vois ici que la recherche de la raison de ne pas évoluer.

Quels sont les avantages que donnent les cours partiels, que vous ne pouvez pas déjà faire avec la langue d'une manière différente ? C'est du bon sucre syntaxique, certes, mais qu'est-ce que le vrai y gagne ? Y a-t-il un exemple concret autre que de le rendre plus semblable à C# ?


A part : pour mémoire, j'ai commencé en tant que développeur C#, puis je suis passé à JavaScript / C#. Une fois que TypeScript 0.8 a été annoncé, j'ai été vendu, non pas parce que c'était C# pour JavaScript, mais parce qu'il prenait du JavaScript strict et le rendait meilleur pour les développeurs qui apprécient les types forts de C#.

TypeScript n'est pas C# et ne doit pas strictement hériter des fonctionnalités de C# simplement parce que C# les possède. Tout comme C# ne doit pas hériter des fonctionnalités de TypeScript. Je ne peux pas compter les fois où j'ai voulu des fonctionnalités telles que les types d'union en C# parce qu'elles sont tellement géniales pour TypeScript, mais elles ne sont pas encore adaptées au langage.


Jusqu'à présent, j'ai lu Génération de code et organisation de code.

Génération de code, regardez Module Augmentation, il y a quelques lacunes que j'ai signalées ici, mais je suis sûr qu'elles peuvent être corrigées.

Organisation du code, je suppose que vous utilisez des régions (lol) ? Il existe de nombreuses autres façons d'organiser votre code, si vous avez une classe de Dieu (pour une raison quelconque), vous pouvez toujours la diviser en plusieurs classes de Dieu. À la surface, la classe dieu est l'importation que tout le monde voit et utilise, mais sous les couvertures, elle est composée de nombreuses classes, peut-être en tant que propriétés de la classe dieu. Si vous utilisez des classes partielles pour l'organisation, je dirais que vous devez refactoriser un peu votre code pour essayer de SOLID ifier votre code.

J'ai pu intégrer l'augmentation dans la plupart des scénarios de génération de code que j'ai rencontrés à ce jour.

Pour Omnisharp-Client, j'utilise l'extension d'interface iciOmniSharp.Api.V2 est généré par réflexion en C#. Au bas du fichier, j'ai un outil qui supprime toutes les méthodes pour cette interface.

Pour RxJS, nous utilisons pour mapper toutes nos méthodes qui sont sur Observable .

Je ne peux tout simplement pas raisonner sur certains des problèmes liés aux classes partielles. Par exemple si on nous donne 3 classes partielles.

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

Portée : Module global (en utilisant namespace / module )

La compilation globale est l'endroit où cela semble être le plus facile. Comme TypeScript fusionne déjà les espaces de noms.

Si mon tsconfig.json ne contient que les chemins de fichiers pour Class1 et Class2, alors tout ce qui est dans Class3 n'est pas automatiquement fusionné.

  • Au début, cela semble être une erreur de l'utilisateur, mais il ne sera pas immédiatement évident pourquoi les méthodes de Class3 ne sont pas incluses. Il s'agit d'un énorme problème d'utilisation qui mènera à la confusion.

Portée : Modules externes (import/export)

Avec la compilation externe, chaque fichier est vraiment considéré comme un module (ou un assemblage d'enfer dans le monde .NET) car chaque module a une liste explicite de toutes ses dépendances (importations) et de toutes ses API publiques (exportations).

Comment raisonnez-vous sur ces scénarios ?

Étant donné une seule référence de fichier, quel est le comportement de la classe ?
Fusionne-t-il automatiquement Class2 et Class3 ?

  • La définition par défaut de Class1, Class2 et Class3 exporte-t-elle exactement la même valeur ?
  • Quel fichier est émis sur le disque ?
  • À quoi ressemblera le JavaScript sous-jacent pour tous les formats pris en charge (amd, umd, commonjs, etc.)
// somefile.ts
import { MyAwesomeClass } from 'MyAwesomeClass1';

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

Doit-on explicitement importer toutes les instances de la classe ? (Si nous le faisons, cela va à l'encontre du but imo).
Que se passe-t-il lorsque vous importez tout dans un fichier, mais pas dans un autre, dans les méthodes de report ?
Cela pourrait conduire à des erreurs vraiment étranges étant donné un graphe de dépendance complexe où la classe est utilisée une fois, sans les partiels supplémentaires. Les valeurs seraient-elles augmentées ? ou les méthodes ne fonctionneraient-elles pas comme par magie jusqu'à ce que l'autre fichier soit chargé qui les amène?

// 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 Juste mes deux cents ici :

C'est du bon sucre syntaxique, certes, mais qu'est-ce que le vrai y gagne ?

Le bon sucre syntaxique n'est-il pas tout l'intérêt de n'importe quelle langue ? D'un point de vue opérationnel, tout ce dont nous avons besoin, ce sont des boucles, des clauses if et des itérations pour tout faire. Le reste n'est que du bon sucre syntaxique afin d'être plus productif et de fournir d'autres qualités non fonctionnelles similaires.

Et tandis que les langages sont généralement bons pour la partie opérationnelle de l'instruction d'un ordinateur, ils sont généralement nuls dans la partie organisationnelle de l'écriture de code. Nous avons ces artefacts culturels ad-hoc comme les objets, les classes, l'héritage et autres, mais aucune base théorique solide, si je ne m'abuse, qui explique vraiment le domaine des opérations d'organisation et toutes les abstractions que nous essayons de construire et de représenter dans notre code source afin pour être en mesure de travailler avec elle d'une bonne manière.

Il y a deux choses que j'aime à propos de TypeScript : 1. Il nous permet d'utiliser du javascript typé afin qu'il soit soudainement gérable de construire des systèmes complexes dans le client. 2. Le système de types est extrêmement expressif (parce qu'il était obligé de pouvoir exprimer toutes sortes de motifs en javascript que les gens pouvaient écrire sans la limitation d'un système de types).

Mais en ce qui concerne la structuration du code, je ne pense pas que ce soit beaucoup moins nul que n'importe quel autre langage. Et je souhaite que nous puissions être plus innovants ici. Donnez aux utilisateurs plus de liberté pour expérimenter la partie organisationnelle du langage. S'ouvrir et rechercher une nouvelle expressivité structurelle au lieu d'être restrictif et méfiant.

Les classes partielles sont non seulement très pratiques pour la génération de code en particulier, mais elles augmentent la liberté d'organisation en général. Liberté dont nous avons besoin pour sortir de ce goudron de l'organisation du code.

@david-driscoll quel est l'intérêt d'avoir des partiels ? Eh bien, encore une fois : génération de code.
Quel est le problème avec votre solution proposée? C'est une solution de contournement. Encore une autre solution de contournement (et une solution de contournement assez sale). Nous avons déjà un langage de merde (javascrtipt), qui regorge de solutions de contournement. Au lieu de penser à leurs tâches principales, les développeurs javascript passent beaucoup de temps à réfléchir aux solutions de contournement. Avec la philosophie que vous proposez, nous pouvons jeter tout le langage TypeScript. Parce que (surprise, surprise) l'ensemble du système de types peut être simulé en javascript pur - en utilisant des solutions de contournement. Pourquoi se soucier d'un langage plus expressif (comme Typescript) si vous pouvez simuler n'importe quoi avec des solutions de contournement ? Pourquoi écrire une seule ligne de code quand la même chose peut être écrite en vingt lignes ? Ramenez les salaires en fonction d'un certain nombre de lignes de code écrites ! Le code court et expressif est pour les chattes, n'est-ce pas ?

Et non : la demande d'avoir des partiels dans TypeScript n'est pas basée sur l'idée que C# les a. Je ne crois pas que TypeScript devrait avoir quelque chose juste pour l'avoir parce qu'un autre langage l'a.

Et enfin : pourquoi pensez-vous que si vous n'utilisez pas quelque chose - personne n'en a besoin ?

@greendimka Je n'essayais pas de susciter l'hostilité : shield:. J'essaye simplement de comprendre les scénarios ou s'il y en a que j'ignore qui franchement est tout à fait possible !

Maintenant, gardez à l'esprit que je ne fais pas partie de l'équipe TypeScript, je suis juste un défenseur, mais l'équipe est restée assez silencieuse ici. L'équipe peut très bien intervenir lorsqu'elle a quelque chose de spécifique à dire, et je m'en remettrai à elle si elle choisit de le faire.

L'un des principaux locataires auxquels l'équipe TypeScript s'est attachée est d'essayer de garder TypeScript synchronisé avec la direction d'ECMAScript et d'éviter de créer des fonctionnalités spécifiques qui pourraient les faire diverger de la direction globale vers laquelle JavaScript évolue.

Ce n'est pas que je ne l'utiliserais pas (je le ferais probablement s'il existait). Le problème est que, dans l'état actuel des choses, les classes partielles ont peut-être des mises en garde, il semble donc douteux qu'elles soient implémentées de si tôt. Cela restera probablement ainsi pendant un certain temps jusqu'à ce que a) cela devienne une fonctionnalité indispensable pour une partie prenante de grande valeur ou b) qu'une proposition passe aux étapes ultérieures du TC39.

Je ne vois pas l'augmentation de module comme une solution de contournement. Il vous permet d'augmenter le système de types et permet de nombreux scénarios de génération de code qui ont été détaillés dans ce fil. Il s'agit d'un pas vers d'autres fonctionnalités linguistiques.

  • C'est moche ? Absolument, moche comme l'enfer. Cela dit, si vous générez le code, quelle est la différence ? Seul votre outil de génération doit se soucier de la manière d'augmenter la classe. Une fois que vous avez exécuté votre outil de génération de code et inclus vos modules, vous obtenez des erreurs complètes d'intellisense et de compilation, etc.

  • Est-ce parfait ? Loin de là! Je vois un scénario beaucoup plus courant avec des mixins devant être pris en charge au niveau de la langue. Et je pense que quelque chose en ligne avec les décorateurs comme proposé ici a du sens, même si encore une fois il n'y a pas de proposition spécifique.

@david-driscoll, désolé d'avoir été extrêmement impoli. J'ai vraiment tendance à me ranger du côté des progrès positifs.

J'aimerais cela pour pouvoir mettre des implémentations statiques dans une classe partielle.

Comme il ne semble pas que cela se concrétisera bientôt, je voudrais proposer une solution de contournement que nous avons trouvée. Il y a des commentaires comme celui-ci, mais je n'en ai pas vu avec ces lectures spécifiques.

Nous aimerions que Partials soit utilisé dans un scénario de génération de code où nous voulons pouvoir étendre notre code TypeScript généré. Cependant, nous générons des modèles qui ont des interdépendances, donc hériter de nos classes ne fonctionne pas bien au sens traditionnel du terme. Les classes générées qui font référence à d'autres classes ne se retrouvent pas avec le bon type d'objet référencé et nous nous retrouverions avec un modèle d'usine complexe pour obtenir les types d'instances corrects créés.

Nous avons fini par changer nos classes générées en classes de base, mais uniquement dans la déclaration de classe. Nous avons ensuite créé des classes stub qui ont hérité de nos nouvelles classes de base. On pourrait alors étendre ces nouvelles classes et elles hériteraient tout leur contenu de la classe de base.

Par exemple:
Si nous générions une classe Person, nous générerions maintenant une PersonBase. Tout le code généré va dans cette classe. Nous générerions également une classe vide Person qui étendrait PersonBase. Cette classe ne serait générée qu'une seule fois. Nous mettons ensuite tout notre code généré dans PersonBase, et tout le code personnalisé va manuellement dans Person. Toutes les références générées à Person restent en tant que Person et non PersonBase. De cette façon, tout IntelliSense continue de fonctionner.

Fichier 1 : Classe de base

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

Fichier 2 : Classe réelle

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

Cela a résolu notre problème de classe partielle avec le code généré. Félicitations à Andrew Scott pour avoir eu l'idée.

J'aimerais beaucoup cela aussi, car je génère du code avec un générateur de code et je dois y ajouter quelques modifications. Les classes partielles permettront de régénérer le code sans avoir à rajouter les modifications plus tard (ce qui peut être volumineux ou complexe)

Il y a une raison importante d'avoir des classes partielles qui, je pense, n'a pas encore été mentionnée : la migration progressive de JS vers TS. En Javascript, en particulier pré-ES6, les classes peuvent ressembler à un tas de :

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

Et ceux-ci peuvent être répartis sur plusieurs fichiers sans aucune manipulation particulière. La conversion d'une base de code comme celle-ci en TypeScript moderne nécessite actuellement le déplacement de fonctions afin que tous les membres d'une classe soient dans le même fichier, ce qui peut être un changement assez invasif. Avec des classes partielles, la migration pourrait être effectuée en utilisant uniquement des modifications locales.

@RyanCavanaugh Vous mentionnez que tout ce qui est demandé ici peut être traité syntaxiquement avec une autre syntaxe TypeScript :

Je pense que la proposition mixin a beaucoup plus de questions ouvertes. La proposition de classe partielle ici n'est qu'une codification des choses qui sont déjà autorisées dans TypeScript, juste avec un peu de sucre syntaxique (cette fonctionnalité pourrait littéralement être faite comme un remappage syntaxique à des choses que nous avons déjà).

Alors, comment procéder en TypeScript ? :
Fichier1.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;
}

Fichier2.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() );
    }
}

Transpiler ce qui précède émettrait une classe JS pour Contact, quelque chose comme ceci :

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

Notez qu'à la fin, je veux une classe nommée Contact et je ne veux pas avoir à sous-classer deux classes distinctes dans une troisième.

@cosmoKenney

Voici un exemple de quelque chose qui fonctionnera. Ce n'est pas aussi syntaxiquement surgaré que partial mais cela fonctionne et c'est une solution très fonctionnelle.

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

Alternativement, vous pouvez également coder pour générer l'interface et utiliser l'extension d'interface qui l'implémente.

Il peut également y avoir des moyens d'utiliser la nouvelle fonctionnalité Mixin, mais je ne me suis pas encore suffisamment plongé là-dedans pour donner une réponse qualifiée.

@david-driscoll Wow. Ma tête vient d'exploser.

Je me demande si la communauté se retrouvera avec un fork, qui prend simplement en charge des classes partielles sans en éliminer un problème.
Jusqu'à présent, je n'ai entendu aucun argument réel contre les classes partielles. Peu de raisons pour justifier une paresse.

@greendimka

Je me demande si la communauté se retrouvera avec un fork, qui prend simplement en charge des classes partielles sans en éliminer un problème.
Jusqu'à présent, je n'ai entendu aucun argument réel contre les classes partielles. Peu de raisons pour justifier une paresse.

Je ne sais pas ce que vous essayez de dire ici. Mais si le sentiment général au sein de la communauté est que nous pouvons obtenir les mêmes résultats en utilisant les fonctionnalités linguistiques existantes, alors j'ai juste besoin de quelques exemples sur la façon de le faire. Ce que @david-driscoll a posté ci-dessus est bien au-delà de ma compréhension. Et ne semble pas résoudre complètement le problème. En fait, d'après ce que je peux dire, il a mal interprété mes intentions.
Ma principale préoccupation est de coder pour générer les propriétés scalaires de la classe, comme un pojo ou une classe de modèle. Mais je dois pouvoir, dans un fichier séparé, ou même dans le même fichier, mais pas dans la définition de classe primaire, ajouter les propriétés d'association (afin de pouvoir coller une définition primaire nouvellement générée par le code sur l'original).
Par exemple, ma classe Contact ci-dessus obtiendrait le code généré avec firstName et lastName. Mais, dans ma définition séparée, j'ajouterais la définition et l'initialisation de la collection d'objets Address.
Mon générateur de code ne connaît que les attributs de la classe, pas les associations, il ne peut donc pas coder la collection d'adresses - comme cela a été fait dans l'exemple de David.

@cosmoKenney, il n'était pas tout à fait clair où l'adresse devrait exister. Excusez-moi de me tromper de contexte. J'essaie juste d'aider à donner les alternatives. Il existe de nombreuses fonctionnalités qui permettent un comportement similaire sans mettre quelque chose dans le compilateur, comme des classes partielles, qui ont beaucoup de considérations supplémentaires et de problèmes potentiels pour implémenter les deux systèmes de modules (interne / externe).

Dans votre cas, générer une classe de base abstraite ou une génération d'interface fonctionnerait, alors votre autre classe en hérite. Ensuite, le fait que votre classe a été générée est toujours caché.

c'est à dire:

// 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 propose une solution intéressante, mais il manque encore la facilité des vraies classes partielles. Comme mes expériences personnelles l'ont montré - les développeurs n'utilisent tout simplement pas de "partiels" qui sont créés de cette manière. Bien que ce soit une bonne solution de contournement, la facilité et le confort des partiels ne sont pas là.

Pour le moment, je ne sais pas comment fonctionne le compilateur TypeScript en interne. Je ne peux que supposer qu'il lit tous les fichiers source, les poursuit et génère des fichiers JS. Si c'est le cas, je ne vois aucun problème à lire une seule classe à partir de plusieurs fichiers source. Si deux fichiers source ou plus d'une même classe fournissent un code conflictuel (par exemple la même propriété définie deux fois), le compilateur lève simplement une exception. Tout comme si vous écrivez du code syntaxiquement invalide.

@greendimka , @david-driscoll
J'ai essayé de compiler l'exemple de David ci-dessus, et ts ne l'aime pas :

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.

De plus, je suis d'accord avec @greendimka pour

@greendimka Je ne sais pas non plus comment fonctionne le compilateur, mais ne sous-estimez pas la tâche. JavaScript n'est pas .NET et les modules ne sont pas disponibles dans le monde entier (vous devez littéralement les importer)

J'aimerais voir cela mis en œuvre, mais cette tâche soulève plusieurs choses qui doivent être soigneusement réfléchies, comme :

  • Si vous définissez une partie de la classe sur un fichier A, une partie sur le fichier B, laquelle doit contenir la classe complète après tranpiling ? Un nouveau doit être généré ?
  • Tous les fichiers contenant des éléments partiels doivent-ils exporter la même classe ?
  • Comment éviter les dépendances cycliques si j'ai besoin du fichier principal sur ces fichiers supplémentaires ?
  • Que se passe-t-il si j'exporte plus de choses sur le module que la classe elle-même ?
  • Vérification des conflits de noms ?

etc...

@greendimka Voir mes réponses ci-dessous : (EDIT : ceci visait @WoLfulus , désolé @greendimka) :

Si vous définissez une partie de la classe sur un fichier A, une partie sur le fichier B, laquelle doit contenir la classe complète après tranpiling ? Un nouveau doit être généré ?

Je serais parfaitement heureux que le fichier A.js ait la définition complète et que le fichier B soit supprimé. Peut-être avec un commentaire en conserve. La plupart d'entre nous regroupent de toute façon, donc la myriade de fichiers .js qui sont regroupés deviennent essentiellement une réflexion après coup.

Tous les fichiers contenant des éléments partiels doivent-ils exporter la même classe ?

Ceci est à peu près répondu par ma réponse à la première question.

Comment éviter les dépendances cycliques si j'ai besoin du fichier principal sur ces fichiers supplémentaires ?

Je ne sais pas. N'est-ce pas le travail du chargeur de module de reconnaître ce scénario ?

Que se passe-t-il si j'exporte plus de choses sur le module que la classe elle-même ?

Je ne vois pas le problème avec ça. En d'autres termes, si B.ts a à la fois une définition partielle et d'autres classes non partielles, alors B.js doit contenir le commentaire en conserve comme mentionné ci-dessus ET les définitions des classes non partielles. Simple, je pense.

Vérification des conflits de noms ?

Comment vous retrouveriez-vous avec un conflit de nom ? Si vous voulez dire sur la classe, alors le mot-clé "partiel" résoudrait cela. Mais alors, si deux autres fichiers définissaient tous les deux des classes avec le même nom, mais sans le mot-clé "partial", le compilateur devrait émettre une erreur sur les types en double -- comme il le fait maintenant. Mais si vous parlez de deux définitions partielles de la même classe définissant une propriété ou une méthode du même nom, le compilateur devrait émettre une erreur sur les membres en double -- comme il le fait maintenant.

@WoLfulus , @cosmoKenney a bien répondu. Juste pour améliorer votre première question (à propos des fichiers A et B) : en tant que concepteur de langage, on a le privilège de définir des règles. J'entends par là que le fichier A peut avoir un tel code "partielle classe X" et le fichier B peut avoir un tel code "partiel (fichierX) classe X", qui produira fileX.js.

@cosmoKenney

Comment éviter les dépendances cycliques si j'ai besoin du fichier principal sur ces fichiers supplémentaires ?
Je ne sais pas. N'est-ce pas le travail du chargeur de module de reconnaître ce scénario ?

TypeScript n'a pas de chargeur de module.

@greendimka

Je me demande si la communauté se retrouvera avec un fork, qui prend simplement en charge des classes partielles sans en éliminer un problème.
Jusqu'à présent, je n'ai entendu aucun argument réel contre les classes partielles. Peu de raisons pour justifier une paresse.

Ce n'est pas une bonne idée. Par exemple, avez-vous réfléchi à la manière dont vous allez maintenir votre fourchette lorsque des importations dynamiques sont ajoutées ?
En outre, de nombreux arguments ont été avancés contre les classes partielles. Briser la correspondance source à source entre les fichiers TypeScript et JavaScript va à l'encontre d'un principe clé du langage. J'imagine qu'une fonctionnalité devrait permettre un scénario infiniment plus précieux que des classes partielles pour que cela soit même pris en compte. Il serait probablement encore rejeté.

@WoLfulus , @cosmoKenney a bien répondu. Juste pour améliorer votre première question (à propos des fichiers A et B) : en tant que concepteur de langage, on a le privilège de définir des règles. J'entends par là que le fichier A peut avoir un tel code "partielle classe X" et le fichier B peut avoir un tel code "partiel (fichierX) classe X", qui produira fileX.js.

Je pense que tu ne fais pas passer ton message. Cela donne l'impression que vous avez l'impression que toutes les limitations que vous rencontrez pour vous exprimer dans n'importe quelle langue existent pour des raisons entièrement arbitraires.
De plus, les questions de reçu de réponse, du moins pas à ma satisfaction.

enfile une combinaison de flammes

TL; DR : Ce n'est pas le cas. Si vous êtes ici au commentaire numéro 189 et que vous souhaitez enregistrer votre désapprobation, veuillez d'abord lire l'intégralité du fil, car les très bonnes raisons de ne pas l'ajouter ont été largement couvertes ci-dessus.

Notre interprétation de cette situation est la suivante :

  • TypeScript a déjà trop de fonctionnalités de classe spécifiques à TS (déclarations de propriétés de constructeur, initialiseurs de membres, décorateurs non finalisés, modificateurs d'accès, implements , etc.) pour quelque chose qui était vraiment destiné à être simplement "ES6 + Types" . C'est en partie de notre faute (notre direction de conception d'origine était généralement trop OOP) et en partie de la faute d'ES6 (la proposition de classe a beaucoup bougé il y a cinq ans et nous avons fini par avoir des fonctionnalités qui ne l'ont pas fait). L'ajout d'une autre caractéristique de classe spécifique à TS est une autre paille sur le dos du chameau que nous devrions éviter si nous le pouvons.
  • Sans ambiguïté, l'avenir de JavaScript, ce sont les modules. Les classes partielles n'ont de sens et fonctionnent bien que dans le modèle de la "soupe mondiale". Autoriser des classes partielles couvrant plusieurs modules est une recette pour un désastre car l'ordre de chargement n'est pas prévisible. L'ajout d'une fonctionnalité qui ne fonctionne bien que dans un univers uniquement global n'est pas une bonne utilisation du temps.
  • C# l'a mais nous ne sommes pas là pour réinventer C#. Sérieusement!
  • Le scénario du « code généré » n'est pas convaincant sur le fond. Toute émission plausible pour les classes partielles restreindrait les initialiseurs de propriété et le code constructeur à exactement une déclaration, et ce serait un dealbreaker pour les configurations de style .Designer.cs car le code utilisateur et le code généré auraient probablement besoin d'initialiseurs ou de logique de constructeur .
  • Il existe de nombreux autres mécanismes de composition disponibles dans JS - mixins, Object.assign , etc. Le scénario qui a conduit à cette fonctionnalité en C# était motivé par des contraintes qui ne sont tout simplement pas présentes dans JS.
  • La solution actuelle de interface + prototype.method = ... ne permet le scénario de code généré aussi bien que partial class serait. C'est bizarre d'écrire ce code à la main mais il n'y a pas de problème pour générer du code différemment, donc si vous pensez vraiment qu'une configuration de code généré par fichier divisé est le seul moyen de résoudre votre problème (je suis sceptique), alors cette méthode est à votre disposition .
  • Nous considérons ES6 comme l'arbitre des "must have" pour les cours. Il n'y a rien de spécial à propos de TypeScript (autre que son attrait pour les programmeurs C#) qui fait qu'il a besoin de classes partielles plus que JavaScript non typé. Donc, s'il y a un scénario qui le met vraiment hors de cause pour l'ajout de classes partielles, alors ce scénario devrait pouvoir se justifier à travers le processus TC39. Si cela gagne du terrain, nous serions heureux d'intervenir, mais cela ne semble même pas être sur le radar de qui que ce soit.

@RyanCavanaugh à ce sujet :

La solution de contournement actuelle de interface + prototype.method = ... active le scénario de code généré aussi bien que la classe partielle le ferait.

Comme je l'ai mentionné plus d'une fois, je suis d'accord avec le fait qu'il existe un moyen non partiel et non c# d'accomplir ce dont j'ai besoin, et je demande simplement un exemple pratique. david-driscoll a été très utile, mais a publié du code qui ne se compile pas. Donc, si vous pensez que je peux coder pour générer une classe avec des propriétés scalaires uniquement pour, par exemple, le prénom, le nom - comme ci-dessus - c'est bien. J'ai juste besoin d'un moyen d'ajouter une collection d'autres types en tant que propriété sur la classe en codant cela à la main. Mais j'ai aussi besoin d'un moyen de gérer l'initialisation de cet ensemble.

@cosmoKenney es-tu sur le site que tu as copié le bon code ? Le deuxième exemple avait des interfaces au lieu du même nom de classe. Je peux joindre un zip du code si vous le souhaitez. J'hésitais juste parce que des fichiers aléatoires sur Internet pouvaient être mauvais et je ne voulais pas que vous pensiez que je publiais quelque chose de malveillant 🙂

Désolé d'entendre cela, mais je respecte les décisions de conception prises ici. J'ai quelques questions si c'est d'accord :

TypeScript a déjà trop de fonctionnalités de classe spécifiques à TS (déclarations de propriétés de constructeur, initialiseurs de membres, décorateurs non finalisés, modificateurs d'accès, implémentations, etc.) pour quelque chose qui était vraiment destiné à être simplement "ES6 + Types". C'est en partie de notre faute (notre direction de conception d'origine était généralement trop OOP) et en partie de la faute d'ES6 (la proposition de classe a beaucoup bougé il y a cinq ans et nous avons fini par avoir des fonctionnalités qui ne l'ont pas fait). L'ajout d'une autre caractéristique de classe spécifique à TS est une autre paille sur le dos du chameau que nous devrions éviter si nous le pouvons.

Compte tenu de cela, une voie possible serait-elle de distinguer clairement, sur le plan de l'organisation et du code, entre le typage pur de JS et les autres constructions de langage proposées par TS ? Pour ma part, j'aime à la fois la dactylographie et les fonctionnalités linguistiques supplémentaires. En tant que consommateur/développeur, je me fiche du fait que le TS ajoute des éléments qui n'existent pas dans JS. Donnez-moi juste des trucs géniaux, si TC39 n'en veut pas, je m'en fiche.

Si TS encapsulait ces éléments les uns des autres, ce serait peut-être plus facile à réutiliser et à créer et à développer par des projets comme SoundScript, au lieu d'être remplacé ?

Et puis un autre projet pourrait s'appuyer sur ce typage pour fournir des constructions de langage meilleures/autres que celles proposées par JS.

Sans ambiguïté, l'avenir de JavaScript, ce sont les modules. Les classes partielles n'ont de sens et fonctionnent bien que dans le modèle de la "soupe mondiale". Autoriser des classes partielles couvrant plusieurs modules est une recette pour un désastre car l'ordre de chargement n'est pas prévisible. L'ajout d'une fonctionnalité qui ne fonctionne bien que dans un univers uniquement global n'est pas une bonne utilisation du temps.

Est ce que c'est vraiment? Bien sûr, les modules feront naturellement partie de JavaScript, mais qu'en est-il du corps de code original principal ? J'adore les namspaces et il n'y a pas de soupe dedans si c'est fait correctement. Je compile le tout dans un seul fichier, et je n'ai pas besoin de chargeurs de modules et dans presque tous les cas, pas besoin de chargement de modules asynchrone. Certaines choses proposées comme https://github.com/Microsoft/TypeScript/issues/420 ne seraient possibles et pertinentes qu'avec des espaces de noms. Êtes-vous en train de dire que ce genre de choses n'arrivera pas parce que nous ne devrions utiliser que des modules ? Les espaces de noms sont-ils sur la voie de la dépréciation ?

@david-driscoll Merci, vous avez déjà été assez utile. Étant donné que @RyanCavanaugh est celui qui continue de clore le problème et de déclarer qu'il existe des solutions de contournement, il devrait peut-être fournir un exemple de solution de contournement.

Je vois aussi beaucoup d'idées fausses sur ce que sont les classes partielles. C'est vraiment une construction simple, et tout le monde souffle cela hors de proportion :
https://msdn.microsoft.com/en-us/library/wa80x488.aspx

Compte tenu de cela, une voie possible serait-elle de distinguer clairement, sur le plan de l'organisation et du code, entre le typage pur de JS et les autres constructions de langage proposées par TS ? Pour ma part, j'aime à la fois la dactylographie et les fonctionnalités linguistiques supplémentaires. En tant que consommateur/développeur, je me fiche du fait que le TS ajoute des éléments qui n'existent pas dans JS. Donnez-moi juste des trucs géniaux, si TC39 n'en veut pas, je m'en fiche.

Ce serait une réécriture d'un langage et casser le code de tout le monde.

De plus, le « Donnez-moi des trucs génial » est très fondamentalement différent des objectifs de conception de TypeScript . Si vous voulez juste des trucs géniaux et que vous ne vous souciez pas de l'alignement sur JavaScript, vous devez choisir un autre langage, comme CoffeeScript , Dart ou Haxe . Bien sûr, il y a peut-être des raisons pour lesquelles ceux-ci ne font pas aussi bien que TypeScript dans l'adoption ...

celui qui continue de clore le problème et de déclarer qu'il existe des solutions de contournement, il devrait peut-être fournir un exemple de solution de contournement

Il existe de nombreux cas d'utilisation pour ce qu'un partial résout. Presque toutes les constructions de langage ont de nombreux cas d'utilisation pour lesquels elles sont valables, mais pour de bonnes raisons, vous devez choisir.

Vous n'arrêtez pas de demander une fonction linguistique spécifique, comme dans « J'aimerais une voiture verte », mais vous n'arrivez pas au cœur du problème : pourquoi la voiture doit-elle être verte ? Si vous avez expliqué pourquoi votre voiture doit être verte, ou si vous êtes ouvert au fait que vous ne vous souciez pas vraiment de la couleur de votre voiture, tant qu'elle répond à vos besoins réels.

Je ne vois pas pourquoi vous pensez qu'il est de l'obligation de Ryan de vous dire comment repeindre votre voiture, simplement parce que pour des raisons valables, le constructeur automobile a décidé de ne pas produire de voitures vertes.

(Oh et les classes mixin ajoutées dans TypeScript 2.2 sont un bon moyen d'accomplir ce que je soupçonne être votre réel besoin)

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

Les mixins

  • Les mixins sont des unités autonomes qui peuvent être ajoutées aux classes existantes.
  • Les classes partielles peuvent accéder aux membres de n'importe quel autre partiel, comme s'ils faisaient partie de la même classe.

À titre d'exercice, essayez d'implémenter la répartition de code suivante avec des 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);
  }
}

À titre d'exercice, essayez d'implémenter la division de code suivante avec des mixins

Alors revenons au fait... Donc, au lieu de signaler une fonctionnalité de langage, quel problème essayez-vous de résoudre avec votre exemple ? Parce que la solution de contournement dans TypeScript est simple :

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

(et si on est completiste, mais encore une fois, ça résout un usage, pas tous les cas d'usage)

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

Compte tenu de cela, une voie possible serait-elle de distinguer clairement, sur le plan de l'organisation et du code, entre le typage pur de JS et les autres constructions de langage proposées par TS ?

Je ne vois pas de moyen de démêler les deux à ce stade. On pourrait, en théorie, écrire un langage à la CoffeeScript qui se transforme syntaxiquement en TypeScript et utiliser ce langage de niveau supérieur pour ajouter de nouvelles fonctionnalités syntaxiques tout en utilisant le système de types de TS, mais cela ne vous mènerait pas loin. Le simple fait de choisir l'un des nombreux autres langages de compilation en JS semble plutôt être un meilleur choix si tel est l'objectif.

Êtes-vous en train de dire que ce genre de choses n'arrivera pas parce que nous ne devrions utiliser que des modules ? Les espaces de noms sont-ils sur la voie de la dépréciation ?

Les espaces de noms ne vont nulle part, c'est sûr. Ils ne sont que le nom d'un modèle qui est déjà largement utilisé et ils ont encore beaucoup de sens dans un monde de modules ES6. Les modules sont de plus en plus la façon dont les gens organisent leur code et ils présentent de nombreux avantages secondaires. Je dis juste que les classes partielles n'ont presque aucun sens dans ce monde, et il serait étrange d'ajouter un modèle d'organisation fondamentalement nouveau qui est incompatible avec cela. Si le monde évoluait dans la direction opposée et que tout le monde se disait "Les scripts globaux avec des effets secondaires sur la charge sont géniaux, tout le monde fait la fête sur les prototype s des autres", peut-être que nous nous sentirions différemment.

@RyanCavanaugh

Peut-être que oui... Peut-être qu'elles n'ont pas autant de sens... Mais comme je l'ai dit à plusieurs reprises, je pense que même dans ce fil, les classes partielles visent à faciliter la génération de code... C'est le principal avantage que je vois d'eux vaut la fonctionnalité dans TS... Moi, et je dois supposer beaucoup d'autres mais ce n'est qu'une supposition, je génère actuellement des tonnes de code TS à partir de mon code C#... Mais alors la question devient de savoir comment étendre en toute sécurité le code généré code TS ??? C'est une question beaucoup plus facile à répondre avec des classes partielles... Actuellement, nous avons recours à des hacks afin de conserver le code personnalisé dans nos fichiers de code TS générés...

Merci

Même chose ici, nous générons le "proxy" tapuscrit pour nos API C#, et nous aimerions pouvoir étendre ces objets en tapuscrit facilement.

Je ne suis pas un spécialiste JS donc je dois manquer quelque chose, car, je ne vois pas pourquoi être capable de diviser la déclaration de classes dans plusieurs fichiers TS (avec une seule déclaration de classe dans un seul fichier JS après compilation) serait un problème pour le monde JS. Pour autant que je le vois, c'est transparent pour JS, comme s'il avait été écrit dans un seul fichier depuis le début. Je veux dire, si vous utilisez des classes partielles ou non, la sortie JS sera exactement la même, mais cela évitera le coût de l'extensibilité des objets JS pour nos développeurs.

@RyanCavanaugh

Une autre chose que je voulais mentionner que moi personnellement, je ne demande pas au compilateur TS de résoudre d'une manière ou d'une autre le dilemme d'emballage qui pourrait survenir lors de la création d'un module ES6 à l'aide de classes partielles dans différents fichiers TS... Il est parfaitement logique pour moi au moins de compiler plusieurs fichiers TS en un seul fichier js pour le module ES6... Encore une fois, les classes partielles aident considérablement à la génération de code... Elles permettent aux outils de créer de grandes parties de votre modèle avec une extensibilité fiable...

@kitsonk

Vous n'arrêtez pas de demander une fonction linguistique spécifique, comme dans « J'aimerais une voiture verte », mais vous n'arrivez pas au cœur du problème : pourquoi la voiture doit-elle être verte ? Si vous avez expliqué pourquoi votre voiture doit être verte, ou si vous êtes ouvert au fait que vous ne vous souciez pas vraiment de la couleur de votre voiture, tant qu'elle répond à vos besoins réels.

Non, je ne demande plus de nouvelle fonctionnalité. Il a été dit à maintes reprises que la langue peut accomplir ce que je veux. J'ai fourni des exemples de ce que je veux (en C#), mais je n'ai pas encore vu dans les exemples utiles un moyen d'arriver là où je dois être.

Je ne vois pas pourquoi vous pensez qu'il est de l'obligation de Ryan de vous dire comment repeindre votre voiture, simplement parce que pour des raisons valables, le constructeur automobile a décidé de ne pas produire de voitures vertes.

Ryan semble être un modérateur ici et clôture le sujet. C'est pourquoi. S'il est une autorité linguistique, il ne devrait peut-être pas clore le problème avant de faire un effort pour comprendre mon besoin et rejeter cette demande sans fournir d'exemple sur la façon de le faire avec les fonctionnalités de la langue maternelle. J'ai déclaré que j'aimerais une solution au moment de la compilation. Et je suis un assez bon développeur et je programme depuis un certain temps dans de nombreux langages différents et obscurs, et j'ai toujours beaucoup de mal avec la syntaxe mixin. Je ne comprends pas comment quelque chose d'aussi complexe et difficile à comprendre est entré dans le langage, et pourtant tout le monde rejette l'élégance de la syntaxe de classe partielle, simplement, semble-t-il, parce qu'elle est empruntée à C#.

Ryan semble être un modérateur ici et clôture le sujet. C'est pourquoi. S'il est une autorité linguistique, alors peut-être qu'il ne devrait pas clore la question avant d'avoir fait un effort pour comprendre mon besoin

??

@RyanCavanaugh , je sais que vous avez fait un effort pour aider. Et à ce stade, je passe à l'essai des mixins. Ou juste l'héritage, ou peut-être que je suis tellement pressé de terminer ce projet que je néglige un moyen de le faire avec des génériques. Hmm...
Avec l'héritage et le nommage, je peux faire :

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

Et ça marche bien pour moi. Ce n'est pas aussi joli et oblige mes classes générées par le code à avoir des noms que je ne veux pas utiliser dans le code. Mais, encore une fois, cela fonctionne.

En ce moment, j'ai l'impression que les gars, qui sont fortement contre les classes partielles, comprennent simplement mal le concept de classes partielles, et ils pensent que les classes partielles sont quelque chose que les classes partielles ne sont pas.

Pour être clair : la classe partielle est une construction syntaxique, qui permet de diviser la définition d'une même classe en plusieurs fichiers physiques. Les mots clés ici sont « même » et « unique ».

La documentation de TypeScript donne une mauvaise définition des classes partielles (premier paragraphe ici : https://www.typescriptlang.org/docs/handbook/mixins.html ).

Exemple de concept de classes partielles réelles :

Fichier "Point.generated.ts":

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

Fichier "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);
  }
}

Ils compilent en "Point.js" - et le nom vient du nom d'une classe, pas des noms de fichiers :

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

Les mixins, lorsqu'ils sont utilisés comme "classes partielles" (et je crois fermement que ce terme dans la documentation est mal utilisé ) représentent en fait un héritage multiple ( https://en.wikipedia.org/wiki/Multiple_inheritance ).

Ainsi, comme nous le voyons, nous discutons de deux outils différents : les classes partielles réelles et l'héritage multiple. Ce sont deux outils différents. Et comme tout outil, ils ont leur propre domaine d'application. En d'autres termes : un menuisier peut utiliser un marteau au lieu d'un maillet, lorsque le maillet n'est pas disponible, mais le marteau n'est pas le bon outil.

À mon humble avis, cette discussion n'a pas d'avenir et nous devrions l'arrêter. Alors que je ne vois toujours pas de problèmes technologiques pour les vraies classes partielles, l'équipe n'a vraiment aucune envie de les implémenter, du moins pour l'instant.

L'équipe TS ne souhaite pas implémenter des fonctionnalités spécifiques à TS si possible. Si vous souhaitez discuter davantage, voici un meilleur endroit : https://esdiscuss.org/topic/class-syntax-enhancements

J'espère qu'il y a un dépôt GitHub du

@greendimka

En ce moment, j'ai l'impression que les gars, qui sont fortement contre les classes partielles, comprennent simplement mal le concept de classes partielles, et ils pensent que les classes partielles sont quelque chose que les classes partielles ne sont pas.

Pour être clair : la classe partielle est une construction syntaxique, qui permet de diviser la définition d'une même classe en plusieurs fichiers physiques. Les mots clés ici sont « même » et « unique ».

Je pense que personne ici ne comprend mal la définition des classes partielles, je pense que vous comprenez peut-être mal la définition des classes en JavaScript.

Si vous avez l'impression que les classes JavaScript sont comme les classes trouvées dans pratiquement n'importe quel autre langage largement utilisé, alors il pourrait bien vous sembler que d'autres ne comprennent pas.

Cependant, comme cela a été dit plusieurs fois dans cette discussion, je sais que je l'ai dit explicitement au moins une fois, les classes JavaScript ne sont pas des constructions déclaratives, elles sont impératives.

Ils n'existent pas tant que les instructions ne sont pas exécutées.

Les définir repose sur la mutation.

Cela les rend déjà fragiles et dépendants de l'ordre en matière d'héritage.

Cela pourrait continuer encore et encore...

@cosmoKenney

Je ne comprends pas comment quelque chose d'aussi complexe et difficile à comprendre est entré dans le langage, et pourtant tout le monde rejette l'élégance de la syntaxe de classe partielle, simplement, semble-t-il, parce qu'elle est empruntée à C#.

Je ne pense vraiment pas que ce soit correct. Tout le monde aime C#, même les programmeurs Java , et TypeScript n'est pas différent pour le simple plaisir d'être différent.

@aluanhaddad

Je pense que vous vous méprenez peut-être sur la définition des classes en JavaScript...

Pour cité et ci-dessous : Je parle du TypeScript.
Comme je l'ai dit : je ne vois aucun problème technique à implémenter de vraies classes partielles dans TypeScript, qui seront compilées dans des constructions de JavaScript.

@greendimka

Pour cité et ci-dessous : Je parle du TypeScript.
Comme je l'ai dit : je ne vois aucun problème technique à implémenter de vraies classes partielles dans TypeScript, qui seront compilées dans des constructions de JavaScript.

Le problème avec cette déclaration, il n'y a pas de classe TypeScript.

Oh mec! Certaines personnes utiliseront n'importe quoi comme raison.
Ok, il n'y a pas de classes dans TypeScript. Ou des classes TypeScript. Ou peu importe. Peu importe.

Je veux dire qu'il s'agit de classes JavaScript. Bien que je sois parfois coupable d'être pédant, je fais très précisément cette distinction parce que nous devons nous mettre d'accord sur la définition du terme classe avant de pouvoir discuter des fonctionnalités qu'il est simple d'y ajouter.

Je pense qu'on n'entend pas la même chose quand on parle de classes et cela provoque des dissonances cognitives et empêche la compréhension mutuelle.

Je pense qu'on ne veut pas dire la même chose quand on parle de classes et cela provoque des dissonances cognitives et empêche la compréhension mutuelle..
Entièrement d'accord!

En fait le premier post de ce topic décrit parfaitement ce qui était demandé, donc cette discussion n'a pas d'avenir :)

@greendimka oui, il n'a pas d'avenir car il semble que TypeScript n'aura jamais de classes partielles. À mon avis, c'est une bonne chose.

Cependant, les malentendus et les problèmes de communication ne sont pas de bonnes choses, c'est pourquoi je continue de discuter avec vous.

Malheureusement, vous ne semblez pas être intéressé non plus

A. En expliquant ce que sont les classes JavaScript, on pourrait changer d'avis et être d'accord avec vous sur le fait qu'elles peuvent être trivialement rendues partialisables.

B. Apprendre des autres ce que sont les classes JavaScript afin de comprendre le point de vue opposé.

Je pense que c'est une honte, mais je n'en discuterai pas davantage si vous le souhaitez.

Je ne suis contre aucune discussion. Mais il a été dit à plusieurs reprises ici que les classes partielles ne seront pas implémentées (du moins pas maintenant). Donc je pense qu'il vaut mieux se concentrer sur d'autres choses. Peut-être que TypeScript pourra être modifié à l'avenir, qui sait.
En ce qui concerne A et B. Je déteste JavaScript. Mais je le connais très bien et, bien sûr, je sais comment les classes y sont « représentées ». Mais le but de toute cette discussion n'était pas de modifier le JavaScript, mais d'améliorer les capacités de TypeScript, en tant que langage supérieur, qui produit du code JavaScript "de bas niveau".
Imaginez que nous remplacerions TypeScript par C++ et JavaScript par du code machine. Le code machine manque de la plupart des concepts qui existent en C++. Mais le C++ devrait-il cesser d'évoluer à cause de cela ? Bien sûr que non. Faut-il arrêter d'évoluer car certains anciens compilateurs ne pourront pas compiler ? Bien sûr que non - vous donnez une nouvelle fonctionnalité aux développeurs et leur dites : cela fonctionne avec de nouveaux compilateurs - vous (développeurs) décidez si vous voulez l'utiliser.

@aluanhaddad
Mec oh mec. Qui se soucie de la partie Javascript de l'équation ? TypeScript est un calque au-dessus, ou comme vous le souhaitez. Vous vous souvenez des anciennes discussions 4GL contre 3GL ? TypeScript est à Javascript comme un 4GL est à un 3GL, en quelque sorte. De plus, l'argument selon lequel TypeScript est ES6 avec des types forts, donc les classes partielles sont en dehors de la portée de la feuille de route de TypeScript est LAME. Nous avons des Mixins, des Génériques, des Modules, des Espaces de Noms et du Type Casting. Alors pourquoi ne pas aller plus loin avec les cours partiels ?

Tout ce que nous voulons des classes partielles, c'est le sucre syntaxique qui nous permet de fusionner toutes les différentes définitions d'une seule classe TypeScript en une seule définition finale - bas niveau - 3GL - Javascript. Il ne devrait y avoir aucun impact sur la définition finale de la classe JavaScript, n'est-ce pas ? Pourquoi le produit final de la transpilation en Javascript fait-il même partie de cette discussion ? Sérieusement.

@cosmoKenney "c'est juste ES.next with types" est un argument de vente important qui convertit les développeurs JavaScript. Si vous voulez quelque chose de plus, vous vous trompez de langue. Essayez peut-être Scala.js à la place ?

edit: Je viens de réaliser une réalisation intéressante que dans ES.next, les classes partielles peuvent être implémentées avec un chargeur de module personnalisé. Si tu utilises

import {MyClass} from './myclass.*'

le chargeur pourrait fusionner toutes les définitions MyClass exportées à partir de tous les fichiers correspondant au caractère générique en une seule classe, puis le fournir.

@spion J'aime la façon dont vous les appelez à juste titre les classes partielles ES.next. Un chargeur de module ES, tel qu'un navigateur, ou un chargeur polyfill, tel que SystemJS, prendrait alors en charge les classes partielles.
L'un des principaux problèmes liés à l'ajout de cette fonctionnalité au niveau TypeScript est qu'elle casse les outils existants tels que les chargeurs et les conditionneurs. D'un autre côté, si ECMAScript les spécifiait, alors tous ces outils implémenteraient la fonctionnalité et TypeScript resterait compatible avec tous ces outils.

Je suis tout à fait d'accord avec vous concernant Scala.js

@cosmoKenney

Nous avons des Mixins, des Génériques, des Modules, des Espaces de Noms et du Type Casting. Alors pourquoi ne pas aller plus loin avec les cours partiels ?

Les mixins tels qu'ils apparaissent dans TypeScript sont un modèle de conception ECMAScript que TypeScript _types_.

Les génériques sont une caractéristique du système de types, ils ne s'appliquent donc pas.

Les modules sont une fonctionnalité ECMAScript.

Les espaces de noms sont un sucre syntaxique et une formalisation d'un modèle de conception ECMAScript.

La conversion de type n'existe pas dans TypeScript.

@aluanhaddad pourquoi continuez-vous à faire de cela une chose à l'exécution ? Les chargeurs de modules et tout ce qui n'a rien à voir avec le transpilage.

+1

@cosmoKenney

@aluanhaddad pourquoi continuez-vous à faire de cela une chose à l'exécution ? Les chargeurs de modules et tout ce qui n'a rien à voir avec le transpilage.

Ce n'est pas correct.

Regardez les écosystèmes SystemJS et Webpack et vous verrez le contraire.

Des workflows encore plus traditionnels et solides comme le roc reposent sur la correspondance entre les fichiers d'entrée et de sortie.

+1

J'ai besoin d'une classe partielle car nous générons la majeure partie de la classe de base à l'aide d'outils (pour automatiser en cas de modification du modèle). Nous utilisons ensuite une classe partielle pour ajouter des fonctionnalités à la classe dans des fichiers séparés afin qu'elle ne soit pas écrasée par l'outil (qui génère automatiquement la classe).

Cette page vous a été utile?
0 / 5 - 0 notes