Typescript: Impossible de définir la fonction statique de 'longueur' sur la classe

Créé le 12 août 2014  ·  22Commentaires  ·  Source: microsoft/TypeScript

Le programme dactylographié suivant est accepté:

class C {
    static length ()  { return "twelve"; }
}

Cependant, dans le code généré:

var C = (function () {
    function C() {
    }
    C.length = function () {
        return "twelve";
    };
    return C;
})();

Ici, une tentative est faite pour affecter la propriété length d'une fonction. Cela ne fonctionne pas (du moins dans Firefox et Chrome), provoquant le blocage des appels ultérieurs de C.length() . Peut-être que l'appel d'une fonction de classe statique length devrait simplement être interdit?

Migré à partir du problème codeplex

Bug Fixed good first issue help wanted

Commentaire le plus utile

Pendant ce temps, le support natif ES6 / 2015 a atterri dans Chrome et Firefox. Si nous observons comment ceux-ci gèrent le problème de manière native, cela se rapproche de ce que @ nicolo-ribaudo et moi avons proposé (voir # 9778).

Extrait pour illustrer le comportement natif:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

En ce qui concerne ce que @tinganho a écrit plus tôt sur la lecture seule de name , length et caller nous pouvons observer pour les implémentations natives que les propriétés sont inscriptibles une fois sur une fonction de constructeur nous avons défini l'un ou l'autre comme un membre de classe statique (n'hésitez pas à revoir ou modifier mes récents avertissements sur MDN concernant les hypothèses dangereuses sur Function.name pour obtenir un nom de classe, à cause de cela).

Donc, utiliser Object.defineProperty comme suggéré par @ nicolo-ribaudo émulerait le comportement natif avec précision. Une chose à prendre en compte est que certaines versions de navigateur plus anciennes mais compatibles ES5 avaient défini les propriétés sur configurable: false . Donc, essayer de les rendre writable: true échouera pour eux (par exemple, voir la configurabilité de Function.name )

Pour résumer, mon point de vue sur la question était:

  • Nous ne pouvons pas utiliser Object.defineProperty() pour la cible es3 compilation Object.defineProperty , exécuter du code ES3 dans un environnement ES5, cependant, poserait le problème de lecture seule. Par conséquent, nous avons besoin d'une erreur de compilation pour la cible es3
  • compilez-le avec Object.defineProperty() et writable: true pour compile-target es5 et émettez un avertissement / erreur indiquant que l'utilisation de ces noms de propriétés peut provoquer des erreurs dans les navigateurs x of version <= y suggestion que, si ces navigateurs doivent être pris en charge, l'option la plus sûre était de choisir un autre nom.
  • si vous ne voulez absolument pas que les gens utilisent les propriétés, générez une erreur de compilation pour l'une ou l'autre cible.

Indépendamment de la sortie de compilation, je pense que tout type de message supplémentaire serait meilleur que la situation actuelle (TS 1.8.10) où nous n'avons aucune indication sur les problèmes potentiels avec la sortie du compilateur.

Edit : Snipped ajouté

Tous les 22 commentaires

Je suis tombé dessus récemment. :(

De plus, quelques autres sont interdits, par exemple le code suivant devrait être une erreur (si nous faisons cette fonctionnalité):

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

Cependant, tous ne sont pas des standards.

Je ne pense pas que les propriétés name , caller et length sont réalisables. Ce sont des propriétés en lecture seule et ne peuvent pas être remplacées. Toutes les affectations qui leur sont attribuées seront ignorées.

@tinganho était d'accord

Ok, mais comme les gens attrapent ce genre d'erreur de temps en temps, je pense que TS devrait les avertir de faire quelque chose de mal. C'est parce que des propriétés comme name ou length sont si naturelles à garder à l'esprit que les gens essaieront de les redéfinir encore et encore.

Peut-être parce que Lengh, le nom sont déjà définis.

Je vais essayer de travailler là-dessus. En dehors de ce qui a déjà été mentionné, y a-t-il d'autres noms de propriétés qui ne devraient pas être autorisés?

Jusqu'à présent, je vois:
longueur, nom, arguments, appelant

Que doit-il se passer exactement quand quelqu'un essaie de définir une propriété statique avec l'un des noms interdits? Erreur du compilateur? Avertissement visible à l'utilisateur?

Je suis nouveau dans ce domaine, donc si je manque quelque chose, alors quelques conseils seraient appréciés. : +1:

Pourquoi ne pas compiler

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

à quelque chose comme

var C = (function () {
    function C() {
    }

    C.__statics = {
        name: 'something',
        arguments: 'args',
        caller: 'caller'
    };

    return C;
})();
console.log(C.__statics.name); // 'something'
console.log(C.__statics.arguments); // 'args'
console.log(C.__statics.caller); // 'caller'

Une question s'est également posée sur stackoverflow: http://stackoverflow.com/a/34644236/390330 : rose:

@zerkms s'il vous plaît ne postez pas le même commentaire à deux endroits; c'est confu.

Vous ne pouvez pas parfois réécrire arbitrairement des noms dans un système de type structurel.

Considérez un code comme celui-ci

interface HasName {
  name: string;
}
class Foo {
  static name = 'fooClass';
}
let bar: HasName = { name: string };
let q = Math.random() > 0.5 ? Foo : bar;
console.log(q.name);

@RyanCavanaugh c'est un bon exemple, en effet (je ne développe pas sur TS, mais bon sang - son système de types est bizarre dès qu'il traite ce code comme valide).

S'il n'est pas possible de les transpiler sans risque, peut-être devrions-nous simplement les interdire?

S'il n'est pas possible de les transpiler sans risque, peut-être devrions-nous simplement les interdire?

Certainement pas changer le transpile, juste en faire une erreur de compilation: rose:

[...] peut-être devrions-nous simplement les interdire?

Certains développeurs entreprenants devraient nous envoyer un PR! :clin d'œil:

Pourquoi ne pas utiliser Object.defineProperty ?

par exemple

class C {
    static length() { return "twelve"; }
}

serait transposé en quelque chose comme

var C = (function () {
    function C() {
    }
    Object.defineProperty(C, "length", {
        value: function () { return "twelve"; },
        writable: true
    });
    return C;
}());

@ nicolo-ribaudo Cela fonctionne en effet. Mon avis: mais je préférerais voir une erreur au lieu d'un tel transpile. TypeScript penche généralement du côté de l'erreur gracieuse au lieu de _fixing JavaScript_: rose:

TypeScript penche généralement du côté de l'erreur gracieuse au lieu de corriger JavaScript

L'idée même de TS n'est-elle pas de corriger le JS en comblant les lacunes qu'il ne peut pas et ne pourra jamais faire.

L'idée même de TS n'est-elle pas de corriger le JS en comblant les lacunes qu'il ne peut pas et ne pourra jamais faire.

Oui. Mais en comprenant comment fonctionne JavaScript. Prenons un exemple de null et undefined . TypeScript choisit de comprendre les deux (au lieu de le consolider en une seule chose comme le fait Dart https://www.dartlang.org/docs/synonymes/). TypeScript donne des erreurs (au lieu de le corriger dans transpile) si vous utilisez le mauvais modèle JavaScript: rose:

Mes opinions sont les miennes et ne sont approuvées par personne d'autre que moi: rose:

Pendant ce temps, le support natif ES6 / 2015 a atterri dans Chrome et Firefox. Si nous observons comment ceux-ci gèrent le problème de manière native, cela se rapproche de ce que @ nicolo-ribaudo et moi avons proposé (voir # 9778).

Extrait pour illustrer le comportement natif:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

En ce qui concerne ce que @tinganho a écrit plus tôt sur la lecture seule de name , length et caller nous pouvons observer pour les implémentations natives que les propriétés sont inscriptibles une fois sur une fonction de constructeur nous avons défini l'un ou l'autre comme un membre de classe statique (n'hésitez pas à revoir ou modifier mes récents avertissements sur MDN concernant les hypothèses dangereuses sur Function.name pour obtenir un nom de classe, à cause de cela).

Donc, utiliser Object.defineProperty comme suggéré par @ nicolo-ribaudo émulerait le comportement natif avec précision. Une chose à prendre en compte est que certaines versions de navigateur plus anciennes mais compatibles ES5 avaient défini les propriétés sur configurable: false . Donc, essayer de les rendre writable: true échouera pour eux (par exemple, voir la configurabilité de Function.name )

Pour résumer, mon point de vue sur la question était:

  • Nous ne pouvons pas utiliser Object.defineProperty() pour la cible es3 compilation Object.defineProperty , exécuter du code ES3 dans un environnement ES5, cependant, poserait le problème de lecture seule. Par conséquent, nous avons besoin d'une erreur de compilation pour la cible es3
  • compilez-le avec Object.defineProperty() et writable: true pour compile-target es5 et émettez un avertissement / erreur indiquant que l'utilisation de ces noms de propriétés peut provoquer des erreurs dans les navigateurs x of version <= y suggestion que, si ces navigateurs doivent être pris en charge, l'option la plus sûre était de choisir un autre nom.
  • si vous ne voulez absolument pas que les gens utilisent les propriétés, générez une erreur de compilation pour l'une ou l'autre cible.

Indépendamment de la sortie de compilation, je pense que tout type de message supplémentaire serait meilleur que la situation actuelle (TS 1.8.10) où nous n'avons aucune indication sur les problèmes potentiels avec la sortie du compilateur.

Edit : Snipped ajouté

@RyanCavanaugh : pourriez-vous s'il vous plaît revoir ce problème pour l'étape TS 2.0.1. La solution semble simple, mais selon l'option que vous choisissez, la sortie de l'émetteur devra peut-être changer (voir mon commentaire précédent). La version de TS 2.0 serait alors préférable d'inclure le correctif.

Les balises sur le PR indiquent que l'équipe TypeScript, qui dispose de ressources limitées, laisse cette possibilité à la communauté de se pencher. Si vous voulez que ce problème soit résolu, quelqu'un dans la communauté au sens large devra s'y attaquer jusqu'à ce que l'équipe de base de TypeScript estime avoir suffisamment de place dans le backlog pour le mettre dans une version (ce qui serait probablement long).

@kitsonk Merci d'avoir expliqué le label PR. Je pense avoir compris cela. Ce que j'ai suggéré était de réévaluer si c'était toujours la bonne façon de traiter le problème. Les propriétés de classe statiques appelées _name_ ou _length_ ne sont pas si improbables et TS produit une sortie erronée pour cela. Par conséquent, je n'appellerais même pas le problème et le «cas de pointe».

Je considère que les propriétés statiques sont au cœur du langage et même s'il n'y a pas encore de pull requests, des solutions au problème ont été présentées dans ce fil.

Néanmoins, je vais évaluer si je peux fournir un PR, mais je dois admettre que je ne connais pas encore les sources TS et j'ai peur que TS 2.0 soit publié avant.

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