在TypeScript中,始终使用.tsx而不是.ts是否有任何不利之处?
在使用TypeScript时,为什么会出现使用.tsx代替.ts的问题以及解决方法?
.tsx扩展名的引入是因为JSX是JS语法的扩展,因此.tsx文件不包含有效的JavaScript代码。
TypeScript也遵循相同的约定,引入了.ts和.tsx扩展名。一个实际的区别是,.tsx不允许使用<Type>
类型断言,因为该语法与JSX标签冲突。作为<Type>
的替代,引入了as Type
断言,并且被认为是一种在.ts和.tsx中始终如一的首选选择。如果在.tsx文件中使用了.ts文件中的代码,则需要修复<Type>
。
使用.tsx扩展名意味着模块与React相关并且使用JSX语法。如果不是这样,扩展名可能会给模块内容和在项目中的作用带来错误的印象,这是反对默认使用.tsx扩展名的论点。
另一方面,如果一个文件与React相关,并且有很大的可能在某个时候包含JSX,那么最好从一开始就将其命名为.tsx,以避免后续重命名。
例如,与React组件一起使用的实用函数可以在任何时候都涉及JSX,因此可以安全地使用.tsx名称,而Redux代码结构不应直接使用React组件,可以与React分开使用和测试,并且可以使用.ts名称。
包含嵌入的jsx元素的测试文件应该具有test.tsx扩展名,以避免出现类似stackoverflow.com/questions/58341545/…的错误。
使用.tsx文件扩展名的一个原因是,当JavaScript处于JSX Harmony模式时,这是一种约定俗成的做法。在这种情况下,文件扩展名并不重要,只要预处理器能够识别您的决定即可(如browserify或webpack)。有些人喜欢将所有的JavaScript文件都使用.js文件扩展名,即使是React代码也是如此。对于TypeScript也是一样,可以使用.ts或.tsx文件扩展名。
现在,我强烈建议在JavaScript中使用JSX语法和在TypeScript中使用React时使用TSX文件扩展名,因为大多数编辑器/IDE将根据文件扩展名来启用或禁用React语法。此外,使用TSX扩展名被认为更加表达性。
尽管如此,这个答案对于关于.ts和.tsx文件的原始问题并不完全准确。在TypeScript中,编译器只会在.tsx文件中启用JSX语法,因为该语法与TS语法(例如<>)存在一些歧义,为了解决这个问题,编译器在.tsx文件和.ts文件中做出了不同的假设。
使用.tsx代替.ts有一些小的差异。.tsx允许在TypeScript中使用jsx标签,但这会引入一些解析上的歧义,使得.tsx略有不同。根据我的经验,这些差异并不是很大:
1. 使用<>进行类型断言不起作用,因为这是jsx标签的标记。
TypeScript有两种类型断言的语法,它们的作用是完全相同的,但其中一种在.tsx中可用,另一种不可用:
let a: any; let s = a as string // 在tsx和ts中都可以使用 let s2 = <string>a // 只在ts中有效
为了保持一致性,我会在.ts文件中也使用as而不是<>。实际上,as是在TypeScript中引入的,因为<>在.tsx中不可用。
2. 没有约束的泛型箭头函数解析不正确。
下面的箭头函数在.ts中是可以的,但在.tsx中会报错,因为<T>在.tsx中会被解析为标签的开始:
const fn = <T>(a: T) => a
可以通过添加约束或不使用箭头函数来解决这个问题:
const fn = <T extends any>(a: T) => a const fn = <T,>(a: T) => a // 这也可以工作,但看起来有点奇怪 const fn = function<T>(a: T) { return a;}
需要注意的是,虽然可以使用.tsx代替.ts,但我不建议这样做。约定是一种强大的东西,人们将.tsx与.jsx相关联,如果你没有任何.jsx标签,他们可能会感到惊讶,最好尽量减少对开发者的惊讶。
虽然上述的歧义(可能不是完整的列表)并不大,但它们可能在决定为新语法使用专用文件扩展名时起到了重要作用,以保持.ts文件的向后兼容性。
关于是否应该将StyleSheet命名为.tsx文件的问题,我建议不要这样做。StyleSheet是在React Native中使用的,它不是一个jsx标签。如果你只想创建一个只包含StyleSheet并导出它的样式文件,你可以使用.ts文件扩展名。