类型“JSX.Element”不可分配给类型“元素”

Posted

技术标签:

【中文标题】类型“JSX.Element”不可分配给类型“元素”【英文标题】:Type 'JSX.Element' is not assignable to type 'Element' 【发布时间】:2021-12-06 15:58:19 【问题描述】:

以前有这个构建“构建”,但升级了我的依赖项,现在有比以前更多的构建错误。一直在运行它们,但我似乎无法解决这个问题。我尝试了多种实现:

  children: Element[];
  Element: JSX.Element;

我已经从这一行删除了JSX.Elementconst VideoSlider: React.FC<Props> = ( content ) => ,希望能解决这个问题,但我不确定..

我真的不知道 Typescript,所以任何帮助将不胜感激,因为我想再次构建这个构建..

错误:

╰─ yarn run build
yarn run v1.22.10
$ next build
info  - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
warn  - Minimum recommended TypeScript version is v4.3.2, older versions can potentially be incompatible with Next.js. Detected: 3.9.10
Failed to compile.

./components/VideoSlider/index.tsx:194:9
Type error: No overload matches this call.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", any,  selectSVG: any; selectBackgroundImage: any; selectVerticalOrientation: any; backgroundSVG: unknown; backgroundImage: unknown; children: Element[]; Element: Element; , never, "div", "div">): ReactElement<...>', gave the following error.
    Type 'JSX.Element' is not assignable to type 'Element'.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<"div", any,  selectSVG: any; selectBackgroundImage: any; selectVerticalOrientation: any; backgroundSVG: unknown; backgroundImage: unknown; children: Element[]; Element: Element; , never, "div", "div">): ReactElement<...>', gave the following error.
    Type 'JSX.Element' is not assignable to type 'Element'.

  192 |         selectVerticalOrientation=content.selectVerticalOrientation
  193 |       >
> 194 |         <FirstSlider>
      |         ^
  195 |           <div className="first-slider background-image-slider">
  196 |             <Slider
  197 |               asNavFor=nav2
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

组件/.tsx 文件:

/* eslint-disable react/jsx-props-no-spreading */
import React,  useState, useRef, useEffect  from "react";
import Slider from "react-slick";
import  Props  from "./interface";
import Video from "../Video";
import 
  VideoSliderComp,
  SliderArrows,
  FirstSlider,
  VideoCopy,
  Slider2Container,
  Slider3Container,
  SliderButtonComp,
  MissingImage,
  ImageContainer,
 from "./styled";
import Layout from "../Layout";
import TextBlock from "../TextBlock";
import  serializers  from "../serializer";
import client from "../../lib/sanityClient";
import imageUrlBuilder from "@sanity/image-url";
import  SanityImageSource  from "@sanity/image-url/lib/types/types";
import MiniTitleComp from "../MiniTitle";

const VideoSlider: React.FC<Props> = ( content ) => 
  const [nav1, setNav1] = useState(null);
  const [nav2, setNav2] = useState(null);
  const [nav3, setNav3] = useState(null);
  const slider1 = useRef(null);
  const slider2 = useRef(null);
  const slider3 = useRef(null);

  useEffect(() => 
    setNav1(slider1.current);
    setNav2(slider2.current);
    setNav3(slider3.current);
  , []);

  const gotoNext = () => 
    slider1.current.slickNext();
  ;

  const gotoPrev = () => 
    slider1.current.slickPrev();
  ;

  const Button = (props: 
    func?: any;
    text?: string;
    first?: boolean;
    last?: boolean;
    right?: boolean;
  ) => 
    const  func, text, first, last  = props;
    return (
      <SliderButtonComp
        first=first
        last=last
        role="button"
        className="arrow-btn prev"
        onClick=func
      >
        <div className="button-container">
          <span className="button">text</span>
        </div>
      </SliderButtonComp>
    );
  ;

  const renderArrows = (i: string | any[]) => 
    if (i.length > 1) 
      return (
        <SliderArrows className="slider-arrow">
          <Button first text="Previous" func=gotoPrev />
          <Button last text="Next" func=gotoNext right />
        </SliderArrows>
      );
    
  ;

  const renderInfo = (slide: 
    videoTitle:
      | boolean
      | React.ReactChild
      | React.ReactFragment
      | React.ReactPortal;
    videoDescription: any;
  ) => 
    return (
      <>
        <h2>slide.videoTitle</h2>
        <TextBlock
          props=slide.videoDescription
          blocks=slide.videoDescription
          serializers=serializers
          imageOptions=
            width: 500,
            height: 500,
          
        />
      </>
    );
  ;

  const settings = 
    customPaging: function () 
      return <div className="dot"></div>;
    ,
    dotsClass: "slick-dots slick-thumb",
  ;

  const checkSlideCountRenderDots = (count: string | any[]) => 
    if (count.length > 1) 
      return true;
     else 
      return false;
    
  ;

  function SvgMissingImage(
    props: JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>
  ) 
    return (
      <MissingImage>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          data-name="Layer 1"
          viewBox="0 0 100 100"
          ...props
        >
          <path d="M57.21 27.558h22.997L57.21 8.032v19.526z" />
          <path d="M59.813 73.568H7.359V9.138h42.104v21.356a4.812 4.812 0 004.81 4.811H78.36v22.24a21.103 21.103 0 011.847-.086 21.036 21.036 0 013.007.22v-23.5a3.734 3.734 0 00-3.734-3.733H56.487a2.165 2.165 0 01-2.166-2.165V8.013a3.734 3.734 0 00-3.733-3.734H4.559A2.06 2.06 0 002.5 6.34v70.03a2.06 2.06 0 002.06 2.058h54.678a20.933 20.933 0 01.575-4.859z" />
          <circle cx=41.062 cy=36.333 r=4.276 />
          <path d="M66.474 62.602L59.797 50.04a1.234 1.234 0 00-1.777-.446l-8.762 5.875a1.234 1.234 0 01-1.865-.656l-2.797-8.897a1.234 1.234 0 00-1.649-.77l-7.163 2.96a1.234 1.234 0 01-1.484-.435l-4.694-6.736a1.234 1.234 0 00-2.14.203l-11.777 26.4a1.234 1.234 0 001.128 1.737h44.528a21.086 21.086 0 015.129-6.673zM80.207 61.134A17.293 17.293 0 1097.5 78.427a17.293 17.293 0 00-17.293-17.293zm-2.919 7.833a2.924 2.924 0 013.204-2.908 3.005 3.005 0 012.633 3.03v10.354a2.919 2.919 0 01-5.837 0zm2.919 21.842a3.007 3.007 0 113.007-3.007 3.007 3.007 0 01-3.007 3.007z" />
        </svg>
      </MissingImage>
    );
  

  const imageOrVideo = (props:  videoSliderBuilder: any ) => 
    return content.videoSliderBuilder.map(
      (
        slide: 
          selectContentType: string;
          image: any;
          videoUrl: string;
          selectVideoType: string;
          video: any;
          video2: any;
        ,
        index: string
      ) => 
        if (slide.selectContentType === "images") 
          let url = urlFor(slide.image).url();
          if (url === null) 
            return <SvgMissingImage />;
           else 
            return <img key="imgfromVideoSliderBuilder" + index src=url />;
          
         else if (slide.selectContentType === "video") 
          return (
            <div key="video-slide" + index>
              <Video
                type="slider"
                key="video" + index
                videoUrl=slide.videoUrl
                selectVideoType=slide.selectVideoType
                videoSliderFile=[slide.video, slide.video2]
                playing=slide.selectVideoType
              />
            </div>
          );
        
      
    );
  ;

  // Get a pre-configured url-builder from your sanity client
  const builder = imageUrlBuilder(client);

  // Then we like to make a simple function like this that gives the
  // builder an image and returns the builder for you to specify additional
  // parameters:
  function urlFor(source: SanityImageSource) 
    return builder.image(source);
  

  return (
    <>
      <VideoSliderComp
        key=content.videoSlider2Title
        selectVerticalOrientation=content.selectVerticalOrientation
      >
        <FirstSlider>
          <div className="first-slider background-image-slider">
            <Slider
              asNavFor=nav2
              ref=slider1
              slidesToShow=1
              fade=true
              arrows=false
              speed=1000
              focusOnSelect=false
              accessibility=false
            >
              content.videoSliderBuilder.map(
                (slide: 
                  backgroundSVG: any;
                  backgroundImage: any;
                  selectSVG: boolean;
                  selectBackgroundImage: React.Key;
                ) => 
                  console.log("slide:", slide);
                  const svgUrl = urlFor(slide.backgroundSVG).url();
                  const backgroundImageUrl = urlFor(
                    slide.backgroundImage
                  ).url();

                  if (
                    slide.selectSVG === true &&
                    slide.backgroundSVG !== undefined &&
                    backgroundImageUrl !== undefined
                  ) 
                    return (
                      <>
                        <div className="crest-container">
                          <img src=svgUrl ? svgUrl : null />
                        </div>
                        <ImageContainer
                          className="imageContainer"
                          selectBackgroundImage=slide.selectBackgroundImage
                        >
                          <img
                            src=backgroundImageUrl ? backgroundImageUrl : null
                          />
                        </ImageContainer>
                      </>
                    );
                   else if (
                    slide.selectSVG === false &&
                    backgroundImageUrl !== undefined
                  ) 
                    return (
                      <ImageContainer
                        key=slide.selectBackgroundImage
                        selectBackgroundImage=slide.selectBackgroundImage
                      >
                        <img
                          src=backgroundImageUrl ? backgroundImageUrl : null
                        />
                      </ImageContainer>
                    );
                   else 
                    return null;
                  
                
              )
            </Slider>
          </div>
          <Layout>
            <div className="content-container">
              <Slider2Container
                selectVerticalOrientation=content.selectVerticalOrientation
                selectOrientation=content.videoSliderBuilder
                className="second-slider video-content-slider"
              >
                <MiniTitleComp title=content.videoSlider2Title />
                <Slider
                  asNavFor=nav3
                  ref=slider2
                  slidesToShow=1
                  swipeToSlide=true
                  focusOnSelect=false
                  arrows=false
                  dots=checkSlideCountRenderDots(content.videoSliderBuilder)
                  ...settings
                >
                  imageOrVideo(content)
                </Slider>
                renderArrows(content.videoSliderBuilder)
              </Slider2Container>
              <Slider3Container
                selectOrientation=content.selectOrientation
                className="third-slider further-info-slider"
                selectVerticalOrientation=content.selectVerticalOrientation
              >
                <Slider
                  asNavFor=nav1
                  ref=slider3
                  slidesToShow=1
                  swipeToSlide=true
                  focusOnSelect=true
                  arrows=false
                  dots=false
                  fade=true
                  speed=1000
                  accessibility=false
                >
                  content.videoSliderBuilder.map(
                    (slide: any, index: string) => 
                      return (
                        <div
                          key="videoSlideBuilder" + index
                          className="further-info-slider__slide"
                        >
                          <VideoCopy>renderInfo(slide)</VideoCopy>
                        </div>
                      );
                    
                  )
                </Slider>
              </Slider3Container>
            </div>
          </Layout>
        </FirstSlider>
      </VideoSliderComp>
    </>
  );
;

export default VideoSlider;

styled.tsx / styled-components:

import styled from "styled-components";

const renderOverlay = (prop: boolean) => 
  let css: string;
  if (prop === true) 
    css = "";
   else if (prop === false) 
    css = null;
  
  return css;
;

const renderVerticalOrientation = (prop: string) => 
  let css: string;
  if (prop === "top") 
    css = "flex-start";
   else if (prop === "center") 
    css = "center";
   else if (prop === "bottom") 
    css = "flex-end";
  
  return css;
;

export const MiniTitle = styled.p`
  margin-bottom: 20px;
  text-align: left;
  font-size: 14px;
  background: #333333;
  color: #cecece;
  padding: 4px 8px;
  display: inline-flex;
  align-self: flex-start;
`;

export const ImageContainer = styled.div< selectBackgroundImage: any >`
  position: relative;
  &::after 
    content: "";
    background: #151515;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: $(props:  selectBackgroundImage: any ) =>
      props.selectBackgroundImage ? "0.666" : null;
  
`;

export const FirstSlider = styled.div<
  selectSVG: any;
  selectBackgroundImage: any;
  selectVerticalOrientation: any;
  backgroundSVG: unknown;
  backgroundImage: unknown;
  children: Element[];
  Element: JSX.Element;
>`
  height: 100vh;
  width: 100%;
  object-fit: contain;
  position: relative;
  margin-bottom: 100px;
  .crest-container 
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1;
    img 
      object-fit: cover;
      height: 100%;
      opacity: 0.855;
      transform: scale(1);
    
  
  .first-slider 
    height: 100%;
    .slick-slider,
    .slick-list 
      height: 100%;
    
    img 
      width: 100%;
    
    position: relative;
    &::after 
      content: $(props:  selectSVG: any ) => (props.selectSVG ? "" : null);
      content: $(props:  selectBackgroundImage: any ) =>
        props.selectBackgroundImage ? "" : null;
      background: #151515;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      opacity: 1.888;
    
    .slick-slide 
      position: relative;
      &:after 
        content: $(props:  selectSVG: any ) =>
          props.selectSVG ? renderOverlay(props.selectSVG) : null;
        content: $(props:  selectBackgroundImage: any ) =>
          props.selectBackgroundImage
            ? renderOverlay(props.selectBackgroundImage)
            : null;

        background: #151515;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 1.888;
      
    
  

  @media only screen and (max-width: 1000px) 
    height: auto;
    overflow: hidden;

    .first-slider 
      .slick-slide 
        height: 100vh;
        height: 100%;
        div,
        img 
          height: 100%;
        
      
    
  
`;

export const SliderContainer = styled.div`
  .second-slider,
  .third-slider 
    display: flex;
    flex-direction: column;
    justify-content: center;
  
`;

export const MissingImage = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  svg 
    width: 33.333% !important;
    fill: #e62117;
  
`;

export const Slider2Container = styled.div<
  selectVerticalOrientation: any;
  selectOrientation: any;
>`
  display: flex;
  flex-direction: column;
  justify-content: center;

  justify-content: $(props:  selectVerticalOrientation: any ) =>
    props.selectVerticalOrientation
      ? renderVerticalOrientation(props.selectVerticalOrientation)
      : null;

  grid-area: content;
  grid-area: $(props:  selectOrientation: any ) =>
    props.selectOrientation ? "additional" : "content";
`;

export const Slider3Container = styled(SliderContainer)<
  selectOrientation: any;
  selectVerticalOrientation: any;
>`
  display: flex;
  flex-direction: column;

  grid-area: additional;
  grid-area: $(props:  selectOrientation: any ) =>
    props.selectOrientation ? "additional" : "content";
  justify-content: $(props:  selectVerticalOrientation: any ) =>
    props.selectVerticalOrientation
      ? renderVerticalOrientation(props.selectVerticalOrientation)
      : null;
  .slick-slider 
    width: 100%;
  
`;

export const VideoSliderComp = styled.div<
  selectVerticalOrientation?: any;
  selectBackgroundImage?: any;
>`
  div 
    &:focus 
      outline: none !important;
    
  
  .slick-dots 
    position: absolute;
    bottom: -40px;
    width: 100%;
    width: auto;
    left: 0;
    li 
      height: initial;
      width: initial;
    
    z-index: 3;
    .dot 
      background: transparent;

      background: #969696;
      border: 1px solid var(--nice-dark);
      border: none;
      padding: 3px;
      border-radius: 100%;
      transform: scale(0.9333);
    
    .slick-active .dot 
      background: white;
      transform: scale(1);
    
  

  .layout 
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    left: 50%;
    transform: translate(-50%, 0);
  

  .content-container 
    height: 100%;
    width: 100%;

    display: grid;
    grid-template-columns: 50% 50%;
    grid-template-rows: auto;
    grid-template-areas:
      "content additional"
      "content additional";
  

  .second-slider 
    grid-area: content;
    height: 100%;
    width: 100%;
    z-index: 2;
    .slick-list 
      overflow: hidden;
    
    .slick-initialized .slick-slide 
      display: flex;
      justify-content: center;
      align-items: center;
      width: 60%;
      overflow: hidden;
      opacity: 0;
      transition: opacity 1s ease;
      transition-delay: 0.2s;
      div 
        width: 100% !important;
      
    
    .slick-slide.slick-active 
      opacity: 1;
      transition: opacity 1s ease;
      transition-delay: 0.1s;
    
    iframe,
    video 
      filter: drop-shadow(0px 4px 0px #333333);
      transition: all 0.666s ease-in 0.1s;
      &:hover 
        filter: drop-shadow(0 4px 0 #484848);
      
    
    video 
      height: initial;
    
  

  .third-slider 
    grid-area: additional;
    color: white;
    align-items: center;
    z-index: 4;
  

  .further-info-slider__slide 
    height: auto;
    display: flex !important;
    align-items: center;
    width: 100%;
    overflow-y: scroll;

    h2 
      display: inline-block;
      position: relative;
    
  

  .player-wrapper 
    position: relative;
    padding-top: 56.25%; /* 720 / 1280 = 0.5625 */
  

  .react-player 
    position: absolute;
    top: 0;
    left: 0;
    height: 100% !important;
  

  @media only screen and (max-width: 1000px) 
    .background-image-slider 
      position: absolute;
      top: 0;
      left: 0;
    

    .layout 
      position: relative;
    

    .further-info-slider__slide 
      height: auto;
      width: 100%;
    

    .content-container 
      display: flex;
      flex-direction: column;
    

    .second-slider 
      overflow: initial;
      margin-bottom: 50px;
    
  

  @media only screen and (max-width: 1000px) 
    .further-info-slider__slide 
      align-items: flex-start;
    
  
`;

export const VideoCopy = styled.div`
  padding: 1em;
  padding-left: 3em;
  padding-right: 3rem;
  width: 95%;
  margin: 0 auto;

  @media only screen and (max-width: 1000px) 
    padding: 0;
    width: 100%;
  
`;

export const SliderButtonComp = styled.div< first: any; last: any >`
  position: relative;
  svg 
    opacity: 1;
    transition: all 0.333s ease-in 0.1s;
  
  .button-container 
    display: flex;
    flex-direction: row;
    align-items: center;
  

  span 
    padding-left: $(props:  first: any ) => (props.first ? "0" : "3px");
    padding-right: $(props:  last: any ) => (props.last ? "0" : "3px");
  
  &:hover 
    .button-container 
      span 
        opacity: 1;
      
      svg 
        opacity: 1;
      
    
  
`;

export const SliderArrows = styled.div`
  grid-area: content;
  position: absolute;
  bottom: -60px;
  width: 100%;
  position: relative;

  display: flex;
  height: auto;
  color: white;
  color: var(--nice-dark);
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  z-index: 2;
  padding: 0;

  .arrow-btn 
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    transition: all 1s ease;
    img 
      width: 30px;
    
    span 
      opacity: 0.8;
      transition: all 0.333s ease-in-out;
    
    &:hover 
      span 
        color: #f9f9f9;
      
    
  
  .prev 
    img 
      transform: rotate(-90deg);
    
  
  .next 
    img 
      transform: rotate(-270deg);
    
  

  @media only screen and (max-width: 1000px) 
    bottom: 0;
  
`;

【问题讨论】:

我知道当您不完全确定问题时可能会很困难,但是当您的问题更简洁时,您将有更好的机会获得答案/帮助 - 您已经包括大量代码供任何人尝试和破译。 你有没有找到解决这个问题的方法? 【参考方案1】:

根据我从您的问题中了解到的情况,您正在尝试将类型功能组件 (JSX.Element) 分配给数组 (Element[])。

试试:

children: Element[];
Element: Array;

【讨论】:

以上是关于类型“JSX.Element”不可分配给类型“元素”的主要内容,如果未能解决你的问题,请参考以下文章

错误 TS2602:JSX 元素隐式具有类型“任何”,因为全局类型“JSX.Element”不存在

类型“null”不可分配给类型“元素”.ts(2345)

类型“()=>元素”不可分配给类型“字符串”

输入'元素 | undefined' 不可分配给类型 'ReactElement<any, string | ((道具:任何)

输入'元素 | undefined' 不可分配给类型 'FC<any> |不明确的'

错误:元素不可分配给反应中的类型字符串