在 React Typescript 中访问 c​​hild.type.name

IT技术 reactjs typescript
2021-05-16 14:03:44

我在整个 Typescript 应用程序中使用 React Functional 组件。

我正在尝试动态更新另一个组件中的一些子组件,如下所示:

const memoizedIterateAndAddProps = useCallback(
    (kids: ReactNode) => {
      return React.Children.map(kids, (child) => {
        if (React.isValidElement(child)){
           console.log(child.type.name)
          }
      }
  }, [])

但是typescript一直在抱怨 Property 'name' does not exist on type 'string | JSXElementConstructor<any>'. Property 'name' does not exist on type 'string'.ts(2339)

我知道这与一个孩子可能只是一个字符串的事实有关,但我无法找到一种让 Typescript 开心的解决方法。

我会非常感谢任何人的帮助

2个回答

React.isValidElement 具有这种类型签名:

function isValidElement<P>(object: {} | null | undefined): object is ReactElement<P>;

在 typeguard 之上,缩小childReactElement具有此类型签名的内容:

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
        type: T;
        props: P;
        key: Key | null;
    }

您可能已经注意到,typestringand 的并集JSXElementConstructor<any>

因此,如果你想确保你有一个处理函数,你应该使用自定义类型保护:

const isFunction=(data:any):data is (...args:any[])=>any => typeof data === 'function'

全码:

import React, { useCallback, ReactNode } from 'react'
const isFunction = (data: any): data is (...args: any[]) => any => typeof data === 'function'

const App = () => {
  const memoizedIterateAndAddProps = useCallback(
    (kids: ReactNode) => {
      return React.Children.map(kids, (child) => {
        if (React.isValidElement(child) && isFunction(child.type)) {
          console.log(child.type.name)
        }
      }
  }, [])

  return null
}

操场

...但我想不出一种让 Typescript 开心的解决方法。

检查它是否不是字符串:

const memoizedIterateAndAddProps = useCallback(
    (kids: ReactNode) => {
        return React.Children.map(kids, (child) => {
            if (React.isValidElement(child) && typeof child.type !== "string") {
//                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
               console.log(child.type.name);
            }
        });
    }
);

(或者&& "name" in child.type也可以。)

您会得到一个字符串,用于说明type何时执行<div/>等操作,因此如果您想使用name.