Y a-t-il un inconvénient à utiliser .tsx au lieu de .ts tout le temps en tapuscrit?

118

Je viens de commencer à travailler sur un projet React avec TypeScript et je me demande que dois-je faire avec les fichiers de classe ordinaires? Dois-je utiliser .tsou des .tsxfichiers et que je ne trouve aucune raison de ne pas utiliser de .tsxfichier tout le temps, même s'il ne s'agit pas d'un projet React!

Y a-t-il une raison ou une situation particulière pour laquelle nous ne devrions pas utiliser de .tsxfichiers? si non, pourquoi l'équipe TypeScript ajoute-t-elle une toute nouvelle extension?

Ostad
la source

Réponses:

145

Vous pouvez utiliser tsxau lieu de tsavec très peu de différence. tsxpermet évidemment l'utilisation de jsxbalises à l'intérieur du typographie, mais cela introduit des ambiguïtés d'analyse qui rendent tsx légèrement différent. D'après mon expérience, ces différences ne sont pas très grandes:

Les assertions de type avec <>ne fonctionnent pas car c'est le marqueur d'une balise jsx.

Typescript a deux syntaxes pour les assertions de type. Ils font tous les deux exactement la même chose mais l'un est utilisable dans tsx, l'autre ne l'est pas:

let a: any;
let s = a as string // ok in tsx and ts
let s2 = <string>a // only valid in ts

J'utiliserais également asau lieu de <>dans des tsfichiers pour la cohérence. asa été introduit dans Typescript car il <>n'était pas utilisable danstsx

Les fonctions fléchées génériques sans contrainte ne sont pas analysées correctement

La fonction de flèche ci-dessous est correcte tsmais une erreur dans tsxas <T>est interprétée comme le début d'une balise danstsx

 const fn = <T>(a: T) => a

Vous pouvez contourner ce problème en ajoutant une contrainte ou en n'utilisant pas de fonction de flèche:

 const fn = <T extends any>(a: T) => a
 const fn = <T,>(a: T) => a // this also works but looks weird IMO
 const fn = function<T>(a: T) { return a;}

Remarque

Bien que vous puissiez utiliser tsx au lieu de ts, je vous le déconseille. Convention est une chose puissante, les gens associent tsxavec jsxet seront probablement surpris que vous n'avez pas des jsxétiquettes, la meilleure surprise développeur de garder au minimum.

Bien que les ambiguïtés ci-dessus (bien que probablement pas une liste complète) ne soient pas grandes, elles ont probablement joué un grand rôle dans la décision d'utiliser une extension de fichier dédiée pour la nouvelle syntaxe afin de garder les tsfichiers rétrocompatibles.

Titien Cernicova-Dragomir
la source
me demande si les signes d'assertion de type <> vont toujours avant l'objet, j'ai vu du code comme produire <IRootStoreStateDeprecated> () et je me suis demandé s'il s'agissait également d'une affirmation de type
Mr-Programs
1
@ Mr-Programme une question différente, mais ce n'est pas une assertion de type qui est une liste d'arguments de type générique. les arguments de type générique viennent après un identificateur an et avant un (où une balise JSX ne peut pas apparaître donc il n'y a pas d'ambiguïté.
Titian Cernicova-Dragomir
61

C'est une sorte de convention à utiliser xà la fin lorsque votre JavaScript est en JSX Harmonymode. Autrement dit, lorsque cela est valide:

doSomething(<div>My div</div>);

Cependant, votre extension de fichier n'a pas vraiment d'importance, tant que vos pré-processeurs sont conscients de votre décision (browserify ou webpack). Pour ma part, j'utilise .jspour tous mes JavaScript, même lorsqu'ils sont React. De même pour tapuscrit, ts/tsx.

ÉDITER

Maintenant, je recommanderais fortement d'utiliser JSX pour Javascript avec la syntaxe React et TSX pour TypeScript avec React car la plupart des éditeurs / IDE utiliseront l'extension pour activer ou non la syntaxe React. Il est également considéré comme plus expressif.

André Pena
la source
9
"Il en va de même pour TypeScript" - ce n'est pas vraiment vrai, la plupart de cette réponse est spécifique à JavaScript et n'est pas vraiment une bonne réponse à la question originale sur tset tsx. Dans TypeScript, le compilateur n'active que la syntaxe JSX dans les .tsxfichiers, car la syntaxe crée une certaine ambiguïté avec la syntaxe TS (comme la <>syntaxe d'assertion), pour résoudre ce problème, le compilateur fait des hypothèses différentes dans un tsxfichier par opposition à un tsfichier. Voir la réponse de Titian Cernicova-Dragomir.
Aaron Beall
6

La raison pour laquelle l'extension .jsx a été introduite est que JSX est une extension de la syntaxe JS et que les fichiers .jsx ne contiennent donc pas de JavaScript valide.

TypeScript suit la même convention en introduisant les extensions .ts et .tsx. Une différence pratique est que .tsx n'autorise pas <Type>les assertions de type car la syntaxe est en conflit avec les balises JSX. as Typeassertions a été introduite en remplacement <Type>et considérée comme un choix privilégié pour des raisons de cohérence à la fois dans .ts et .tsx. Dans le cas où le code de .ts est utilisé dans le fichier .tsx, <Type>il devra être corrigé.

L'utilisation de l'extension .tsx implique qu'un module est lié à React et utilise la syntaxe JSX. Si ce n'est pas le cas, l'extension peut donner une fausse impression sur le contenu du module et le rôle dans le projet, c'est l'argument contre l'utilisation de l'extension .tsx par défaut.

D'un autre côté, si un fichier est lié à React et a de bonnes chances de contenir JSX à un moment donné, il peut être nommé .tsx depuis le début pour éviter de le renommer plus tard.

Par exemple, les fonctions utilitaires qui sont utilisées avec les composants React peuvent impliquer JSX à tout moment et peuvent donc utiliser en toute sécurité des noms .tsx, alors que la structure de code Redux n'est pas censée utiliser directement les composants React, peut être utilisée et testée indépendamment de React et peut utiliser des noms .ts.

Fiole d'Estus
la source
4

Je crois qu'avec les fichiers .tsx, vous pouvez utiliser tout le code JSX (JavaScript XML). Alors que dans le fichier .ts, vous ne pouvez utiliser que du texte dactylographié.

theITvidéos
la source
2

.tsles fichiers ont une <AngleBracket>syntaxe d'assertion de type qui entre en conflit avec la grammaire JSX. Afin d'éviter de briser une tonne de personnes, nous utilisons .tsxpour JSX et avons ajouté la foo as Barsyntaxe autorisée dans les fichiers .tset .tsx.

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

Et l'autre est la syntaxe as:

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

On peut utiliser .ts avec as-syntaxmais <string>someValuec'est cool!

Arjun Kava
la source