typescript 将props传递给子渲染函数的 Package 器组件

anauzrmj  于 2023-06-07  发布在  TypeScript
关注(0)|答案(1)|浏览(170)

我试图输入一个 Package 器组件,它接受一个title prop和一个children prop,这是一个函数。传递给 Package 器的所有其他prop都应该在呈现子对象时用作参数:

import React, { ReactNode, InputHTMLAttributes } from "react"

type WrapperProps<P extends object> = {
    title: string
    children: (props: P) => ReactNode
} & P

const Wrapper = <P extends object>({ title, children, ...rest }: WrapperProps<P>) => {
    return children(rest)
}

type InputProps = { type: string, name: string }

const WrappedInput = (inputProps: InputProps) => <Wrapper
    title="Hello, World"
    {...inputProps}
>{(props) => <input {...props} />}
</Wrapper>

我不明白两件事:
1.在Wrapper组件中,当调用children(rest)时,编译器指示参数可分配给类型为“P”的约束,但“P”可以用约束“object”的不同子类型示例化。P可以示例化什么,这将是不兼容的?我可以强制转换rest as P,但我想知道问题是什么。
1.在WrappedInput组件中,编译器认为props对象(在children render函数中)具有childrentitle属性。当我明确地说调用children的参数是P类型,而P没有这些属性时,怎么会这样呢?

fkvaft9z

fkvaft9z1#

这里的主要问题是,正如你在第二个问题中提到的,传递给render函数的props是P类型,但是作为泛型,P被用来捕获所有的props,而不管它们是如何被拆分和使用的。
所以对于你的第一个问题,如果你考虑一种情况,你想传递给children的props也包含一个title字段,并且类型不一定是字符串,那么类型是不相关的。
对于你的第二个问题,这也涉及到第一个问题,最快的方法,同时改变最少的当前结构是指定类型的儿童参数为省略<P,“标题”|“孩子们”,正如你在这里看到的。 这并不完全像您指定的那样,泛型P仍然具有childrentitle属性。你可以尝试说P扩展了一些东西,不允许像P extends Omit<Record<string,unknown>, "title"|"children"这样的东西尝试满足这个条件,但相当肯定的是,这在 typescript 中不起作用,你不能指定扩展一些记录否定某些字段,链接到[https://github.com/microsoft/TypeScript/issues/31153](https://github.com/microsoft/TypeScript/issues/31153)。 但是不要认为这是一个大问题,如果P`拥有所有的属性也没关系,您可以从子渲染参数中省略它们。

type WrapperProps<P extends object> = {
    title: string
    children: (props: Omit<P,"title"|"children">) => ReactNode
} & P

您可能还想将object更改为类似Record<string,unknown>的东西,因为object将接受数组之类的东西,Record通常更适合用于props。
你也可以改变你的类型,这样P就可以完全是子对象的props,但是你不能把它们扩展到主props类型上。就像这样

type WrapperProps<P extends Record<string, unknown>> = {
  title: string;
  children: (props: P) => ReactNode;
  childrenProps: P;
};

那么类型就没有不确定性了,因为P只用作子函数的参数,并用作WrapperProps上自己的字段。
希望有帮助

相关问题