V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
loveyou1
V2EX  ›  问与答

react + ts 类型检测问题?求解答。

  •  
  •   loveyou1 · 2020-07-04 17:29:46 +08:00 · 3278 次点击
    这是一个创建于 1389 天前的主题,其中的信息可能已经有所发展或是发生改变。

    基础代码

    import React from 'react';
    
    interface Prop {
      children: React.ReactNode
    }
    
    
    class Person extends React.Component<Prop, {}> {
      constructor(props: Prop) {
        super(props);
        this.state = {};
      }
      
      render() {
        return (
          <div>
            // 这个地方报错
            { this.props.children({ x: 30, y: 40 }) }
          </div>
        );
      }
    }
    

    报错内容

    (property) React.Component<Prop, {}, any>.props: Readonly<Prop> & Readonly<{
        children?: React.ReactNode;
    }>
    不能调用可能是 "null" 或“未定义”的对象。ts(2723)
    
    (property) children: React.ReactNode
    不能调用可能是 "null" 或“未定义”的对象。ts(2723)
    此表达式不可调用。
      不可调用 "string | number | boolean | {} | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)> | ReactNodeArray | ReactPortal" 类型的任何组成部分。ts(2349)
    

    另一种写法,不报错

    import React from 'react';
    
    interface Prop {
      children: React.ReactNode
    }
    
    
    class Person extends React.Component<Prop, {}> {
      constructor(props: Prop) {
        super(props);
        this.state = {};
      }
    
      render() {
        const props: any = this.props;
        return (
          <div>
             // 这样不会报错
            { props.children({ x: 30, y: 40 }) }
          </div>
        );
      }
    }
    

    问题

    • 为什么报错,我不是已经给他做了类型声明了吗
    • 怎么解决
    • react + ts 有没有什么好的文档推荐

    ** 勿喷我,觉得问题简单,不愿意回复的请退出去 **

    15 条回复    2020-07-05 01:14:55 +08:00
    BigOldBrother
        1
    BigOldBrother  
       2020-07-04 17:51:42 +08:00 via Android
    我理解的你只是给 constructor 函数的 props 参数定义了类型,下边的 this.props 是实例上的了,不是一个东西
    loveyou1
        2
    loveyou1  
    OP
       2020-07-04 18:05:11 +08:00
    @BigOldBrother

    import React from 'react';

    interface Prop {
    children: React.ReactNode
    }


    class Person extends React.Component<Prop, {}> {
    constructor(props: Prop) {
    super(props);
    this.state = {};
    }

    render() {
    // 这里这样
    const props: Prop = this.props;
    return (
    <div>
    { props.children({ x: 30, y: 40 }) }
    </div>
    );
    }
    }

    这种情况也报错
    withzhaoyu
        3
    withzhaoyu  
       2020-07-04 18:10:47 +08:00
    children 断言是 reactNode, 其实是个方法?我看你有传参 {x:30,y:40}
    toma77
        4
    toma77  
       2020-07-04 18:11:49 +08:00 via iPhone
    children 换个名字试试?
    loveyou1
        5
    loveyou1  
    OP
       2020-07-04 18:15:05 +08:00
    @withzhaoyu
    我就想试一试 react + ts,谁知道一试就出问题
    因为这个组件是这么写的
    <Person>
    {(mouse: any) => (
    <p>鼠标的位置是 {mouse.x},{mouse.y}</p>
    )
    </Person>
    loveyou1
        6
    loveyou1  
    OP
       2020-07-04 18:15:57 +08:00
    @toma77
    换不了吧,children 就是代表组件内部的节点
    sun876592293
        7
    sun876592293  
       2020-07-04 18:20:54 +08:00
    this 调用的是类成员,你得看看子类和父类有没有这个成员,不是声明了 传个形参就行的
    Raincal
        8
    Raincal  
       2020-07-04 18:48:24 +08:00
    ```js
    children: (mouse: { x: number; y: number }) => React.ReactNode
    ```
    noe132
        9
    noe132  
       2020-07-04 18:51:48 +08:00
    如果是 React.ReactNode 请直接{this.props.children}
    如果你要传个 render function 进来,请把 children 的类型改了。

    另外不推荐这样做,建议用 render props.
    dremy
        10
    dremy  
       2020-07-04 18:58:39 +08:00 via iPhone
    这不就是 children 版的 render props,那得把 children 定义成对应的函数类型

    另外现在的 Hooks 解决这类问题更加合适和方便,建议通过自定义 Hooks 而不是通过类组件的 render props 来实现
    loveyou1
        11
    loveyou1  
    OP
       2020-07-04 19:04:20 +08:00
    @Raincal 这个 🆗,不懂就问,为啥 children: React.ReactNode 这个 this.props 就报错了
    @noe132 我就试着玩,正式写不会这么写
    loveyou1
        12
    loveyou1  
    OP
       2020-07-04 19:07:27 +08:00
    @dremy 我就试着玩的
    Raincal
        13
    Raincal  
       2020-07-04 19:21:05 +08:00
    @loveyou1 #11 报错的原因上面已经有人说了,你的另一种写法不报错是因为在 render 里把 props 定义为 any 了
    weixiangzhe
        14
    weixiangzhe  
       2020-07-05 00:13:11 +08:00 via Android
    看这个库: https://github.com/typescript-cheatsheets/react-typescript-cheatsheet

    children 你定义的是一个 renderprops 写法 对应的是 function 才对,上面的 md 里写的情景很全了,建议看一遍
    ke1vin
        15
    ke1vin  
       2020-07-05 01:14:55 +08:00
    这不是很明显吗,children 应该是 Function
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   970 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 21:26 · PVG 05:26 · LAX 14:26 · JFK 17:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.