` | `` | `.jsx` |
| `react` | `` | `React.createElement("div")` | `.js` |
| `react-native` | `` | `` | `.js` |
可通过命令行标志`--jsx`或在`tsconfig.json`文件中的相应选项,来对此模式进行指定。
> *注意:* 标识符`React`是硬编码的,因此必须要有`R`开头的React。
## `as`运算符(The `as` Operator)
回顾一下类型断言(a type assertion)是怎么写的:
```typescript
var foo = bar;
```
这里对变量`bar`有着类型`foo`进行了断言。因为TypeScript也将尖括号用于类型断言,因此JSX的语法就引入了一些解析困难。结果就是,TypeScript不允许在`.tsx`文件中出现尖括号类型断言。
为了弥补`.tsx`文件中的这个功能损失,就加入了一个新的类型断言运算符:`as`。使用`as`运算符,上面的示例就可很容易写出来。
```typescript
var foo = bar as foo;
```
在`.ts`与`.tsx`文件中,都可以使用`as`运算符,其作用与其它类型断言样式一致。
## 类型检查(Type Checking)
为了理解JSX下的类型检查,就必须首先掌握固有元素与基于值的元素的区别(In order to understand type checking with JSX, you must first understand the difference between intrinsic elements and value-based elements)。对于一个JSX表达式``,`expr` 既可以是对环境中固有元素(比如DOM环境中的`div`或`span`)的参考,也可以是对某个创建出来的组件的参考。因为以下两个原因,这一点很重要:
1. 对于React, 固有元素生成的是字符串(`React.createElement("div")`),但对于创建出的组件则不是(`React.createElement(MyComponent)`)。
2. 传入给JSX的属性的类型,应以不同的方式进行查找。固有元素属性应本质上就知道,而组件将期望给它们指定一套属性(The types of the attributes being passed in the JSX element should be looked up differently. Intrinsic element attributes should be known *intrinsically* whereas components will likely want to specify their own set of attributes)。
对于如何区分二者,TypeScript使用了[与React相同的约定](http://facebook.github.io/react/docs/jsx-in-depth.html#html-tags-vs.-react-components)。固有元素总是以小写字母开头,而基于值的元素则全部以大写字母开头。
### 固有元素(Intrinsic elements)
固有元素是在一个特殊接口`JSX.IntrinsicElements`上查找的。默认情况下,如果没有指定该接口,那么什么都可以且固有元素不会被检查类型。但如果指定了该接口,那么固有元素的名称将作为一个属性,在`JSX.IntrinsicElements`上进行查找。比如:
```typescript
declare namespace JSX {
interface IntrinsicElements {
foo: any
}
}
; // 没有问题
; // 错误
```
在上面的示例中,``将正确工作,但``将因为其没有在`JSX.IntrinsicElements`上进行指明,而导致一个错误。
> 注意: 也可以像下面这样,在`JSX.IntrinsicElements`上指定一个全能字符串索引器(a catch-all string indexer)。
```typescript
declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}
```
### 基于值的元素(Value-based elements)
基于值的元素,是简单地通过作用域中的标识符进行查找的。
```typescript
import MyComponent from "./MyComponent";
; // 没有问题
; // 错误
```
基于值元素的定义有两种方式:
1. 无状态函数式组件方式(Stateless Functional Component, SFC)
2. 类组件方式(Class Component)
因为在JSX表达式中二者难于区分,所以首先会尝试使用 **过载方案** 来将表达式作为无状态函数式组件进行解析(Because these two types of value-based elements are indistinguishable from each other in JSX expression, we first try to resolve the expression as Stateless Functional Component using **overload resolution**)。加入该过程成功,那么就完成了将表达式解析为其声明。而在将其解析为SFC失败时,就会尝试将其作为类组件进行解析。加入仍然失败,就会报告一个错误。
***关于无状态函数式组件***
***Stateless Functional Components***
如同该名称所体现的那样,这种组件是以首个参数为`props`对象的JavaScript函数进行定义的。这里要强调,其定义函数的返回值,必须是可赋值给`JSX.Element`的类型
```typescript
interface FooProp {
name: string;
X: number;
Y: number;
}
declare function AnotherComponent (prop: {name: string});
function ComponentFoo (prop: FooProp) {
return ;
}
const Button = (prop: {value: string}, context: { color: string }) =>