首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确扩展TypeScriot接口?应该只有一个孩子

如何正确扩展TypeScriot接口?应该只有一个孩子
EN

Stack Overflow用户
提问于 2022-05-20 12:13:59
回答 1查看 159关注 0票数 0

我在用私人公司的图书馆制作手风琴。我使用的是TS 4.6.4和React 17。根据docs,如果有多个子程序,它就能工作:

代码语言:javascript
复制
question
answer
question
answer
question
answer

然而,我得到了错误:

代码语言:javascript
复制
This JSX tag's 'children' prop expects a single child of type 'ReactChild | undefined', but multiple children were provided.

此错误显示在:

代码语言:javascript
复制
  <StyledAccordion onChange={onChange}>
      <dt>Question(SBTi)?</dt>
      <div>answer </div>
      <dt>Question(SBTi)?</dt>
      <div>answer </div>

StyledAccordion是一个样式化的组件:

代码语言:javascript
复制
export const StyledAccordion = styled(Accordion)``

该组件的接口包括:

代码语言:javascript
复制
export interface AccordionProps {
....
....
    children?: ReactChild;
....
....

因此,我试图扩展这个接口,使其通过TypeScript.我觉得这里的打字稿写得不好.

我正在尝试这样做:

代码语言:javascript
复制
interface MultipleChildrenAccordion extends AccordionProps {
  children?: React.ReactChild[]|React.ReactNode|undefined;
}

然而,我得到了:

代码语言:javascript
复制
Interface 'MultipleChildrenAccordion' incorrectly extends interface 'AccordionProps'.
  Types of property 'children' are incompatible.
    Type 'ReactChild[] | ReactNode' is not assignable to type 'ReactChild | undefined'.
      Type 'null' is not assignable to type 'ReactChild | undefined'.ts(2430)

你帮我接受多个孩子会很感激的.

提前谢谢你

编辑:我已经用以下方式更新了类型:

代码语言:javascript
复制
type MultipleChildrenAccordion = Omit<AccordionProps, 'children'> & {
  children?: React.ReactChild[]|React.ReactNode|undefined;
}

然而,现在在<StyledAccordion onChange={onChange}>上我得到了:

代码语言:javascript
复制
No overload matches this call.
  Overload 1 of 2, '(props: { onChange?: ((accordion: AccordionAPI, openItems: number[]) => void) | undefined; ref?: Ref<AccordionAPI> | undefined; key?: Key | null | undefined; ... 8 more ...; iconProps?: IconProps | undefined; } & { ...; } & { ...; }): ReactElement<...>', gave the following error.
    Type '{ children: Element[]; onChange: (() => void) | undefined; }' is not assignable to type '{ onChange?: ((accordion: AccordionAPI, openItems: number[]) => void) | undefined; ref?: Ref<AccordionAPI> | undefined; key?: Key | null | undefined; ... 8 more ...; iconProps?: IconProps | undefined; }'.
      Types of property 'children' are incompatible.
        Type 'Element[]' is not assignable to type '(ReactChild & (string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal | ReactChild[] | null)) | undefined'.
          Type 'Element[]' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>> & ReactChild[]'.
            Type 'Element[]' is missing the following properties from type 'ReactElement<any, string | JSXElementConstructor<any>>': type, props, key
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<ForwardRefExoticComponent<AccordionProps & RefAttributes<AccordionAPI>>, any, Omit<AccordionProps, "children"> & { ...; }, never, ForwardRefExoticComponent<...>, ForwardRefExoticComponent<...>>): ReactElement<...>', gave the following error.
    Type '{ children: Element[]; onChange: (() => void) | undefined; }' is not assignable to type '{ onChange?: ((accordion: AccordionAPI, openItems: number[]) => void) | undefined; ref?: Ref<AccordionAPI> | undefined; key?: Key | null | undefined; ... 8 more ...; iconProps?: IconProps | undefined; }'.
      Types of property 'children' are incompatible.
        Type 'Element[]' is not assignable to type '(ReactChild & (string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal | ReactChild[] | null)) | undefined'.
EN

回答 1

Stack Overflow用户

发布于 2022-05-20 12:28:38

当你扩展一个类型时,你只能使它变窄,而不是变宽。如果允许您将其扩展,这将基本上破坏子类型。考虑一下这个例子:

代码语言:javascript
复制
interface Person {
  name: string;
}

const someFunction = (person: Person) => {
  console.log(person.name.toUpperCase()); // Should be just fine: name is a string, strings have a toUpperCase property
}

const example: Person = {
  name: 'bob'
}
someFunction(example);

现在我想从人身上伸出来。类型记录将允许我缩小范围,例如将名称限制在特定的字符串上。这个扩展类型可以传递到someFunction中,someFunction仍然可以工作:

代码语言:javascript
复制
interface SpecificPerson extends Person {
  name: 'bob' | 'alice' | 'eve',
}
const example2: SpecificPerson = {
  name: 'alice'
}
someFunction(example2);

但如果我被允许把事情做得更广泛,那么someFunction就会崩溃。不再命名为字符串,因此当someFunction试图调用.toUpperCase()时,将引发异常。

代码语言:javascript
复制
interface Entity extends Person {
  name: string | number; // Typescript won't actually let me do this
}
const example3: Entity = {
  name: 42,
}
someFunction(example3); // This shows a typescript error at compile time, and would throw a runtime error if it was allowed.

操场连接

如果您想要一个类似于AccordionProps的类型,但它将子类型替换成更广泛的类型,您可以这样做,但它不会从AccordionProps扩展。您将无法在期望AccordionProps的地方使用它:

代码语言:javascript
复制
type MultipleChildrenAccordionProps = Omit<AccordionProps, 'children'> & {
  children?: React.ReactChild[]|React.ReactNode|undefined;
}

请注意,手风琴不能使用这种类型。如果手风琴的实现使得它只支持一个孩子,那么你必须给它一个孩子。

取决于手风琴是如何实现的,也许您可以传递一个片段:

代码语言:javascript
复制
<StyledAccordion onChange={onChange}>
  <>
    <dt>Question(SBTi)?</dt>
    <div>answer </div>
    <dt>Question(SBTi)?</dt>
    <div>answer </div>
  </>
</StyledAccordion>

或者如果这不起作用,给它一个div:

代码语言:javascript
复制
<StyledAccordion onChange={onChange}>
  <div>
    <dt>Question(SBTi)?</dt>
    <div>answer </div>
    <dt>Question(SBTi)?</dt>
    <div>answer </div>
  </div>
</StyledAccordion>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72318746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档