React JSX

    • 使用文件后缀 (替代 .ts);
    • 在你的 tsconfig.json 配置文件的 compilerOptions 里设置选项 "jsx": "react"
    • 在你的项目里为 JSXReact 安装声明文件:npm i -D @types/react /react-dom
    • 导入 react 到你的 .tsx 文件(import * as React from 'react')。

    React 不但能渲染 HTML 标签(strings)也能渲染 React 组件(classes)。JavaScript 触发这些的原理是不同的(React.createElement('div') vs React.createElement(MyComponent)), 确定使用哪一种方式取决于首字母的大小写,foo 被认为是 HTML 标签,Foo 被认为是一个组件。

    一个 HTML 标签 foo 被标记为 JSX.IntrinsicElements.foo 类型。在我们已经安装的文件 react-jsx.d.ts 中定义了所有主要标签的类型,如下是一部分示例:

    函数式组件

    你可以使用 React.FunctionComponent 接口定义函数组件:

    1. type Props = {
    2. foo: string;
    3. };
    4. const myComponent: React.FunctionComponent<Props> = props => {
    5. return <span>{props.foo}</span>;
    6. };
    7. <MyComponent foo="bar" />;

    类组件

    根据组件的 props 属性对组件进行类型检查。这是以 JSX 如何转换做为蓝本,例如:属性成为 props 的组成部分。

    react.d.ts 文件定义了 React.Component<Props,State>,你应该使用自己所需的 PropsState 声明扩展它:

    1. type Props = {
    2. foo: string;
    3. };
    4. class MyComponent extends React.Component<Props, {}> {
    5. render() {
    6. return <span>{this.props.foo}</span>;
    7. }
    8. }
    9. <MyComponent foo="bar" />;

    React JSX Tip: 接收组件的实例

    react 类型声明文件提供了 React.ReactElement<T>,它可以让你通过传入 <T/>,来注解类组件的实例化结果。

    1. class MyAwesomeComponent extends React.Component {
    2. render() {
    3. return <div>Hello</div>;
    4. }
    5. }
    6. const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
    7. const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error!

    当然,你可以将它用作函数参数的注解,甚至可以是 React 组件的 prop 成员。

    类型 React.Component<Props>React.ComponentClass<P>React.StatelessComponent<P> 的组合,所以你可以接受一些可以用作 Props 类型和使用 JSX 渲染的组件。

    1. const X: React.Component<Props> = foo; // from somewhere
    2. // Render X with some props:
    3. <X {...props} />;

    React JSX Tip: 可渲染的接口

    React 可以渲染一些像 JSX 或者是 string 的内容,这些被合并到类型 React.ReactNode 中,因此,当你接收可渲染的内容时,你可以使用它:

    React JSX tip: 接收组件的接口

    React 声明文件提供 React.ReactElement<T> 的接口,可以让你注解一个类组件实例化的返回值<T/>,如:

    1. class MyAwesomeComponent extends React.Component {
    2. render() {
    3. return <div>Hello</div>;
    4. }
    5. }
    6. const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
    7. const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error!

    TIP

    你也可以将其用做函数参数的注解,或者是 React 组件的 prop 注解。

    React JSX tip: 接收可以做为 props 的组件,并且使用 JSX 渲染它

    1. const X: React.Component<Props> = foo // 来自其他地方
    2. // 渲染 X
    3. <X {...props} />

    它完全能按我们预期工作,如:

    1. // 一个泛型组件
    2. type SelectProps<T> = { items: T[] };
    3. class Select<T> extends React.Component<SelectProps<T>, any> {}
    4. // 使用
    5. const Form = () => <Select<string> items={['a', 'b']} />;

    泛型函数

    一些像下面这样的正常工作:

    1. function foo<T>(x: T): T {
    2. return x;
    3. }

    然而不能使用箭头泛型函数:

    解决办法:在泛型参数里使用 extends 来提示编译器,这是个泛型:

    1. const foo = <T extends {}>(x: T) => x;

    React Tip: 强类型的 Refs

    基本上你在初始化一个变量时,使用 ref 和 null 的联合类型,并且在回调函数中初始化他:

    1. class Example extends React.Component {
    2. example() {
    3. // ... something
    4. }
    5. render() {
    6. return <div>Foo</div>;
    7. }
    8. }
    9. exampleRef: Example | null = null;
    10. render() {
    11. return <Example ref={exampleRef => (this.exampleRef = exampleRef)} />;
    12. }
    13. }

    使用原生元素时也一样:

    1. input: HTMLInputElement | null = null;
    2. render() {
    3. return (
    4. <input
    5. ref={input => (this.input = input)}
    6. value={this.props.value}
    7. onChange={e => {
    8. this.props.onChange(e.target.value);
    9. }}
    10. />
    11. );
    12. }
    13. focus() {
    14. if (this.input != null) {
    15. this.input.focus();
    16. }
    17. }
    18. }

    类型断言

    • 在有状态组件中使用默认的 Props:你可以通过 null 操作符(这不是一个理想的方式,但是这是我能想到的最简单的最小代码解决方案)告诉 TypeScript 一个属性将会被外部提供(React)。
    1. class Hello extends React.Component<{
    2. /**
    3. * @default 'TypeScript'
    4. */
    5. compiler?: string;
    6. framework: string;
    7. }> {
    8. static defaultProps = {
    9. compiler: 'TypeScript'
    10. };
    11. render() {
    12. const compiler = this.props.compiler!;
    13. return (
    14. <div>
    15. <div>{compiler}</div>
    16. <div>{this.props.framework}</div>
    17. </div>
    18. );
    19. }
    20. }
    21. ReactDOM.render(
    22. <Hello framework="React" />, // TypeScript React
    23. );

    原文: