JSX
一种嵌入式的类似XML的语法。 它可以被转换成合法的JavaScript。常见的有React,博客所用到的库为inferno也是jsx。
JSX模式
|模式| 输入| 输出| 输出文件扩展名|
|preserve| <div />
| <div />
|.jsx|
|react| <div />
| React.createElement(“div”)| .js|
|react-native| <div />
| <div />
|.js|
as 操作符
1 | var foo = <foo>bar; |
上述代码将bar变量断言为foo类型。但是在jsx语法中解析会很困难。因此jsx禁用了尖括号的写法。ts通过提供 as 操作符来让jsx语法更好的实现断言。as操作符在ts和tsx文件都可以使用,与尖括号的行为是等价的
类型检查
固有元素与基于值的元素之间的区别
为什么要区分固有元素与基于值的元素
- 对于React,固有元素会生成字符串(React.createElement(“div”)),然而由你自定义的组件却不会生成(React.createElement(MyComponent))
- 传入JSX元素里的属性类型的查找方式不同
固有元素总是以一个小写字母开头,基于值的元素总是以一个大写字母开头
固有元素
如果指定了接口JSX.IntrinsicElements
,则通过接口查找,如果接口没有指定则全部通过,不对固有元素进行检查。
1 | declare namespace JSX { |
基于值的元素
基于值的元素会简单的在它所在的作用域里按标识符查找
1 | import MyComponent from "./myComponent"; |
有两种方式可以定义基于值的元素:
- 函数组件 (FC)
- 类组件
由于这两种基于值的元素在JSX表达式里无法区分,因此TypeScript首先会尝试将表达式做为函数组件进行解析。如果解析成功,那么TypeScript就完成了表达式到其声明的解析操作。否则尝试以类组件进行解析,如果依旧失败,则抛出错误
函数组件
TypeScript会强制函数组件的返回值可以赋值给JSX.Element
,由于函数组件是简单的JavaScript函数,所以我们还可以利用函数重载。
1 | interface ClickableProps { |
类组件
类组件的类型允许自定义。但是需要分清两个术语:元素类的类型
元素实例的类型
对于 class 来说,类类型是类的构造函数和静态部分。实例类型是class的实例的类型
对于工厂函数来说,类类型为函数,实例类型为函数的返回值类型
元素的实例类型必须赋值给JSX.ElementClass
或抛出一个错误。默认的JSX.ElementClass
为{}
,但可以被扩展用来限制JSX的类型以符合相应的接口
属性类型检查
属性类型检查的第一步是确定_元素属性类型_。 这在固有元素和基于值的元素之间稍有不同
对于固有元素,是JSX.IntrinsicElements属性的类型
1 | declare namespace JSX { |
对于基于值的元素,取决于先前确定的在元素实例类型上的某个属性的类型。至于该使用哪个属性来确定类型取决于JSX.ElementAttributesProperty
它应该使用单一的属性来定义。 这个属性名之后会被使用
TypeScript 2.8,如果未指定JSX.ElementAttributesProperty,那么将使用类元素构造函数或函数组件调用的第一个参数的类型
1 | declare namespace JSX { |
属性的检查支持支持可选属性和必须属性
JSX还会使用JSX.IntrinsicAttributes接口来指定额外的属性,这些额外的属性通常不会被组件的props或arguments使用,例如React里的key。
JSX.IntrinsicClassAttributes
子孙类型检查
TypeScript 2.3 引入了children类型检查。利用JSX.ElementChildrenAttribute
来决定children名。JSX.ElementChildrenAttribute
应该被声明在单一的属性(property)里。
1 | declare namespace JSX { |
如不特殊指定子孙的类型,我们将使用React typings 里的默认类型
JSX结果类型
默认地JSX表达式结果的类型为any,可以自定义这个类型,通过指定JSX.Element接口
不能够从接口里检索元素,属性或JSX的子元素的类型信息。 它是一个黑盒