首页 > 解决方案 > 如何使用 TypeScript 以类型安全的方式访问 React 子元素道具?

问题描述

我正在尝试访问props我的应用程序中的 React [Native] 组件(保证是我的自定义类型元素的实例ItemTemplate

const children = React.Children.toArray(this.props.children);
return children.find(t => t.props.itemKey == key);

但是,在我尝试访问的第二行中,我t.props得到:

Property 'props' does not exist on type 'ReactElement<ItemTemplate, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | ... 13 more ... | (ReactElement<...>[] & ReactPortal)'.
  Property 'props' does not exist on type 'ReactElement<ItemTemplate, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)>[] & string'.

该代码确实可以正常工作,但 TypeScript (3.6.3) IntelliSense 抱怨。为什么?

标签: reactjstypescriptreact-nativereact-propstypescript-types

解决方案


在这种情况下,您需要将子项声明或强制转换为 ReactElement。这里我有一个从 nextjs 到自定义 NavLink 的 Link 组件示例:

import { ReactElement, cloneElement } from 'react';
import Link, { LinkProps } from 'next/link';

type NavigationData = {
    currentPath: string;
    pathsToMatch: string[] | string;
    activeClassName: string;
    children: ReactElement;
};

type NavLinkProps = LinkProps & NavigationData;

export default function NavLink({
    currentPath,
    pathsToMatch,
    activeClassName,
    children,
    ...props
}: NavLinkProps): ReactElement {
    function GetActiveLink(
        currentPath: string,
        paths: string | string[],
        activeClassName: string
    ): string {
        if (currentPath === '/' && paths === '/') {
            return activeClassName;
        } else if (currentPath !== '/' && paths.indexOf(currentPath) !== -1) 
        {
            return activeClassName;
        }

        return '';
    }

   let className: string = children.props.className || '';
   className += ` ${GetActiveLink(currentPath, pathsToMatch, activeClassName)}`;

    return <Link {...props}>{cloneElement(children, { className })}</Link>;
}

通过这种方式,您可以在没有任何警告的情况下访问属性道具。

快乐的代码。:-)


推荐阅读