Update JSX page. PR596

This commit is contained in:
zhongsp 2017-10-09 08:52:09 +08:00
parent 678de4fb36
commit 9bd4921c57

View File

@ -102,7 +102,57 @@ import MyComponent from "./myComponent";
<SomeOtherComponent />; // 错误
```
可以限制基于值的元素的类型。
有两种方式可以定义基于值的元素:
1. 无状态函数组件 (SFC)
2. 类组件
由于这两种基于值的元素在JSX表达式里无法区分因此我们首先会尝试将表达式做为无状态函数组件进行解析。如果解析成功那么我们就完成了表达式到其声明的解析操作。如果按照无状态函数组件解析失败那么我们会继续尝试以类组件的形式进行解析。如果依旧失败那么将输出一个错误。
### 无状态函数组件
正如其名组件被定义成JavaScript函数它的第一个参数是`props`对象。
我们强制它的返回值可以赋值给`JSX.Element`。
```ts
interface FooProp {
name: string;
X: number;
Y: number;
}
declare function AnotherComponent(prop: {name: string});
function ComponentFoo(prop: FooProp) {
return <AnotherComponent name=prop.name />;
}
const Button = (prop: {value: string}, context: { color: string }) => <button>
```
由于无状态函数组件是简单的JavaScript函数所以我们还可以利用函数重载。
```ts
interface ClickableProps {
children: JSX.Element[] | JSX.Element
}
interface HomeProps extends ClickableProps {
home: JSX.Element;
}
interface SideProps extends ClickableProps {
side: JSX.Element | string;
}
function MainButton(prop: HomeProps): JSX.Element;
function MainButton(prop: SideProps): JSX.Element {
...
}
```
### 类组件
我们可以限制类组件的类型。
然而,为了这么做我们需要引入两个新的术语:*元素类的类型*和*元素实例的类型*。
现在有`<Expr />`*元素类的类型*为`Expr`的类型。
@ -238,9 +288,78 @@ var badProps = {};
<foo {...badProps} />; // 错误
```
## 子孙类型检查
从TypeScript 2.3开始,我们引入了*children*类型检查。*children*是*元素属性(attribute)类型*的一个属性(property)。
与使用`JSX.ElementAttributesProperty`来决定*props*名类似,我们可以利用`JSX.ElementChildrenAttribute`来决定*children*名。
`JSX.ElementChildrenAttribute`应该被声明在单一的属性(property)里。
```ts
declare namespace JSX {
interface ElementChildrenAttribute {
children: {}; // specify children name to use
}
}
```
如不特殊指定子孙的类型,我们将使用[React typings](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)里的默认类型。
```ts
<div>
<h1>Hello</h1>
</div>;
<div>
<h1>Hello</h1>
World
</div>;
const CustomComp = (props) => <div>props.children</div>
<CustomComp>
<div>Hello World</div>
{"This is just a JS expression..." + 1000}
</CustomComp>
```
你也可以像其它属性一样指定*children*的类型。下面我们重写[React typings](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)里的默认类型。
```ts
interface PropsType {
children: JSX.Element
name: string
}
class Component extends React.Component<PropsType, {}> {
render() {
return (
<h2>
this.props.children
</h2>
)
}
}
// OK
<Component>
<h1>Hello World</h1>
</Component>
// Error: children is of type JSX.Element not array of JSX.Element
<Component>
<h1>Hello World</h1>
<h2>Hello World</h2>
</Component>
// Error: children is of type JSX.Element not array of JSX.Element or string.
<Component>
<h1>Hello</h1>
World
</Component>
```
# JSX结果类型
默认地JSX表达式结果的类型为`any。
默认地JSX表达式结果的类型为`any`
你可以自定义这个类型,通过指定`JSX.Element`接口。
然而不能够从接口里检索元素属性或JSX的子元素的类型信息。
它是一个黑盒。