Typescript: لا يحتوي نوع عنصر JSX على أي تكوين أو توقيعات استدعاء في v3.2.0-rc

تم إنشاؤها على ٢١ نوفمبر ٢٠١٨  ·  27تعليقات  ·  مصدر: microsoft/TypeScript

إصدار TypeScript: 3.2.0-rc ، 3.2.1

الشفرة

import * as React from "react";
import { Component, ReactType} from "react";
function App(props:{component:ReactType}) {
  const Comp: ReactType = props.component
  return (<Comp />)
}

سلوك متوقع:
يجب إخراج عادي كـ TypeScript 3.1.6

السلوك الفعلي:
TS2604: JSX element type 'Comp' does not have any construct or call signatures.

Bug JSTSX Duplicate

التعليق الأكثر فائدة

بالنسبة لي كان الحل:

export type WrapperProps = {
    mainApp: React.ElementType
}

ال 27 كومينتر

يفتقد هذا لبقية رسالة الخطأ ، ولكن تأكد من أنك تستخدم أحدث إصدار من @types/react وأنه لا توجد نسخ مكررة منه في node_modules أو ملف القفل.

تحرير: ربما تقصد استخدام نوع المكون وليس ReactType

تضمين التغريدة

لقد تأكدت من استخدام أحدث @types/react 16.7.7 وعدم وجود تكرارات @types/react في yarn.lock .
إذا كانت المشكلة بسبب تكرار @types/react ، فستُرجع الخطأ Duplication of definition ... .

أعود إلى "typescript": "^3.1.6" ثم يعمل بشكل طبيعي.

الكتابة المطبوعة 3.2.1

مثال آخر


interface P1 {
  p?: boolean
  c?: string
}

interface P2 {
  p?: boolean
  c?: any // if you replace c with string, error goes away
  d?: any
}

declare var C: React.ComponentType<P1> | React.ComponentType<P2>


const a = <C p={true} /> // element does not have any ...

يبدو أن المشكلة تتعلق بالتغييرات الجديدة "مميّزات لاغية". يبدو أن ts لا يمكنها العثور على واجهة مشتركة لتلك الأنواع.
مثال آخر

interface P1 {
  p?: any
  c?: string // remove this and it's ok
}

interface P2 {
  p?: boolean
}

لدينا مشكلة مشابهة ، مثال سريع:

import * as React from 'react'

//
// Types
//

interface Config<P> {
  ElementType: React.ReactType<P>
}

interface EmptyProps {
}

interface Props {
  a?: string
}

type HProps = {
  configEmpty: Config<EmptyProps>,
  config: Config<Props>
}

//
// Component
//

const H: React.FC<HProps> = ({ config, configEmpty }) => {
  const A: React.ReactType<EmptyProps> = configEmpty.ElementType // assigned
  const B: React.ReactType<EmptyProps> = 'div' // assigned

  const C: React.ReactType<Props> = config.ElementType // assigned
  const D: React.ReactType<Props> = 'div' // in this case assignment failed

  return (
    <div>
      <A/> {/* TS2604: JSX element type 'A' does not have any construct or call signatures. */}
      <B/>

      <C/>
      <D/>
    </div>
  )
}

export default H

أرى أن هذا السلوك غير صالح تمامًا ، لأن A و B لهما نفس الأنواع . في الوقت نفسه ، يكون لدى B و D _ أنواع مماثلة_ ، لكن D غير قابل للتخصيص 🤔

الكود في الريبو: https://github.com/layershifter/ts-issue

لا يفعلون ذلك ، لأنك تستخدم const . نوع A هو typeof configEmpty.ElementType ، لكن نوع B هو 'div' . سيؤدي استخدام let s إلى إظهار نفس السلوك في كليهما.

Kovensky ماذا عن A و C ؟ لماذا C أعمال بينما A فشل مع does not have any construct الخطأ؟

هذا لأنني قمت بتحسين نوع ReactType لاستبعاد المكونات التي لن تتمكن من تلقي الدعائم التي تقدمها لها. نظرًا لأنه لا يمكن لأي عنصر من عناصر DOM تلقي { a: string | undefined } ، فقد تم استبعادهم جميعًا ، ولا يزال يُسمح فقط بتعيين مكونات الوظيفة / الفئة لها.

Kovensky شكرًا لك 👍 الآن مشكلة التعيين واضحة بالنسبة لي ، لكن ماذا عن هذا؟

import * as React from 'react'

//
// Types
//

interface Config<P> {
  ElementType: React.ReactType<P>
}

interface Empty {}
interface Props { a?: string }

type HProps = {
  configEmpty: Config<Empty>,
  config: Config<Props>
}

//
// Component
//

const H: React.FC<HProps> = ({ config, configEmpty }) => {
  const A: React.ReactType<Empty> = configEmpty.ElementType // is React.ReactType<Empty>
  const B: React.ReactType<Empty> = 'div' // is string
  const C: React.ReactType<Props> = config.ElementType // is React.ReactType<Props>

  return (
    <div>
      {/* React.ReactType<Empty> */} <A/> {/* <--- TS2604: JSX element type 'A' does not have any construct or call signatures. */}
      {/* React.ReactType<Empty> */} <B/>
      {/* React.ReactType<Props> */} <C/>
    </div>
  )
}

export default H

A و B لهما نفس الأنواع المحددة بوضوح ، لماذا فشل A ؟ إنه أمر محير حقًا.

ربما أقول إن خطأrexpan و goloveychuk مشابه للخطأ # 28795 و # 28768 بناءً على مُنشئ JSX الشرطي.

حسنًا ، تكمن المشكلة في أن ReactType<any> يُرجع اتحادًا من _ كل علامة jsx مضمنة_ (بالإضافة إلى ComponentType<any> ، لكن هذا الجزء لا يمثل مشكلة) ، والتوقيعات الخاصة بهذه المكونات لا تبسط بشكل تافه (يوجد ليس توقيعًا يشمل جميع الآخرين تمامًا). هذا أيضًا يعتمد على # 7294 ليتم إصلاحه. على الجانب الإيجابي ، فإن التغيير الأساسي المطلوب لإصلاح جميع مشكلات JSX التي يتم الإبلاغ عنها هو نفسه.

بالنسبة للسياق ، نقوم بتصنيع نوع مثل هذا بشكل فعال:

declare const JsxSigs: {[K in keyof JSX.IntrinsicElements]: ((props: JSX.IntrinsicElements[K]) => JSX.Element)}[keyof JSX.IntrinsicElements];

والذي ينتهي به الأمر باعتباره اتحادًا لعدد من التوقيعات الفريدة

قبل أن أغيره ليكون اتحادًا لجميع علامات jsx المدمجة ، كان _just_ string | ComponentType<any> ، والذي كان أسوأ من ذلك.

نعم ، خاصةً منذ ما قبل 3.2 ، اكتب string في علامة بهدوء _disabled_ typechecker ، لأن خطأ "الفهرس غير موجود" الذي كان من المفترض أن يصدره لم يحدث أبدًا.

تم وضع علامة على هذه المشكلة على أنها مكررة ولم تشهد أي نشاط في اليوم الماضي. تم إغلاقه لأغراض التدبير الآلي للمنزل.

الوقوع في مشكلة قد تكون ذات صلة. لدي المكون التالي:

function MaybeLabel(props: { useLabel: boolean }) {
   const { useLabel } = props;
   const TagName = useLabel ? 'label' : 'div';

   return <TagName>Woookie</TagName>
}

مما يؤدي إلى

error TS2604: JSX element type 'TagName' does ليس have any construct or call signatures.

في حين

function MaybeLabel2(props: { useLabel: boolean }) {
   const { useLabel } = props;
   const TagName = useLabel ? 'span' : 'div';

   return <TagName>Woookie</TagName>
}

مقبول تمامًا للمترجم المطبوع عليه. كما هي:

export function MaybeLabel3(props: { useLabel: boolean }) {
    const { useLabel } = props;
    const TagName = useLabel ? 'label' : 'div';

    return React.createElement(TagName, 'Wookie')
}

حيث الاختلاف الوحيد في MaybeLabel2 هو أنني أستخدم span بدلاً من label (يبدو استخدام span بدلاً من div مقبولاً أيضًا ). MaybeLabel3 يجعل الأمر أكثر غرابة ، حيث يجب أن يكون هذا بالضبط ما يجمعه MaybeLabel .

باستخدام أحدث إصدار من @ types / رد فعل و @ أنواع / رد فعل دوم ، وتحقق من المشكلة في النسخ 3.2.1 و 3.2.2 و 3.3.0-dev.20181219. في 3.1.6 يعمل كل شيء كما هو متوقع (لا ينتج عن أي من الأمثلة أخطاء)

بالنسبة لي كان الحل:

export type WrapperProps = {
    mainApp: React.ElementType
}

@ TacB0sS يرجى توضيح ذلك.

ربما أساء فهم الموضوع ، لكنني أردت تمرير مرجع إلى عنصر jsx إلى عنصر jsx آخر:

export const AppWrapper = hot(module)((props: WrapperProps) => {

    const MainApp = props.mainApp;
    if (!MainApp)  // <-- JSX elements MUST start with upper case!!
        throw new ImplementationMissingException("mainApp was not specified!!");

    return (
        <Router history={BrowserHistoryModule.getHistory()}>
            <MainApp prop1={"value"}/>
        </Router>)
});

معا مع:

export type WrapperProps = {
    mainApp: React.ElementType<{prop1:string}>
}

@ TacB0sS بالنسبة لي كانت الحيلة الرئيسية هي إضافة حالة if . يبدو أنه لا يهم ما إذا كنت تستخدم React.ComponentType أو React.ElementType

لست متأكدًا من فهمي لنتائج ذلك. لدي خطأ مشابه لم أتمكن من حله. ها هي حالة الاستخدام الخاصة بي:

// Logo.tsx

import classNames from 'classnames';

interface Props extends React.HTMLAttributes<HTMLElement> {
  tag?: React.ReactType;
}

const Logo: React.SFC<Props> = props => {
  const { tag: Tag = 'div', className, ...rest } = props;
  return (
    <Tag
      className={classNames(styles.logo, className)}
      {...rest}
      dangerouslySetInnerHTML={{ __html: logo }}
    />
  );
};

ثم أستخدمه على هذا النحو في مكون آخر مثل:

const Header: React.SFC<{}> = () => {
  return (
    <div>
      <Logo tag="h1" aria-label="Syn By Design: Eric Masiello's Portfolio" />
      Header online
    </div>
  );
};

عندما أقوم بتشغيل المترجم ، أتلقى هذا الخطأ:

components/Logo.tsx:13:6 - error TS2604: JSX element type 'Tag' does not have any construct or call signatures.

13     <Tag
        ~~~


Found 1 error.

أي أفكار حول كيفية جعل هذا العمل؟

بدلاً من Component ، استخدم ComponentClass

تلقيت هذا الخطأ لأنني استوردت افتراضيًا لكنني أعلنت أن التصدير المقابل باسم اسمه بدلاً من الافتراضي في الملف .d.ts ... أربكني لبعض الوقت

أردت فقط إضافة هذا هنا. لست متأكدًا مما إذا كان هذا قد قيل بالفعل ولكن إذا كنت تقوم بعمل مكون طلب توظيف ، فأنت تريد استخدام النوع React.ComponentType

. " https://flow.org/en/docs/react/types/#toc -react-componenttype"

ericmasiello انتهى بي الأمر باستخدام React.ElementType لمكون تم تمريره ديناميكيًا. حالة الاستخدام الخاصة بي هي في الأساس ما يلي:

type Props = {
    heading: React.ElementType
}
const Header: FC<Props> = props => {
    const Header = props.heading ?? 'h2';
    return (
        <Header className="some-class"><children /></Header>
    )
}

ericmasiello انتهى بي الأمر باستخدام React.ElementType لمكون تم تمريره ديناميكيًا. حالة الاستخدام الخاصة بي هي في الأساس ما يلي:


type Props = {

    heading: React.ElementType

}

const Header: FC<Props> = props => {

    const Header = props.heading ?? 'h2';

    return (

        <Header className="some-class"><children /></Header>

    )

}

رائع! ما هو إصدار Typescript وما هو إصدار @ types / رد فعل قمت بتثبيته؟

تضمين التغريدة

رائع! ما هو إصدار Typescript وما هو إصدار @ types / رد فعل قمت بتثبيته؟

اكتب [email protected]
@ أنواع / رد @

لقد قمت بحل هذه المشكلة عن طريق القيام بأي من هذين الأمرين:

حالة 1:

ملف d.ts:

declare module "foo" {
   interface PropFoo {
      propy: string;
   }

   class MyTypedComponent extends React.Component<PropFoo> { }
}

تتفاعل:

import MyTypedComponent from "foo";

function AnotherComponent() {

   /* Notice in here we have to use the dot operator and reference the component */
   return <MyTypedComponent.MyTypedComponent /> 
}

لاحظ أنه من أجل استخدام المكون المكتوب حديثًا ، يتعين علينا كتابة _MyTypedComponent.MyTypedComponent_. قد يكون هذا واضحًا لبعض الأشخاص ، لكنني أهدرت الكثير من الوقت عندما كان كل ما كان علي فعله هو استخدام عامل التشغيل النقطي عند استيراد المكون والإشارة إليه.

الحالة 2 [مجرد طريقة أخرى لكتابة الحالة 1]:

ملف d.ts:

declare module "foo" {
   interface PropFoo {
      propy: string;
   }

   export default class MyTypedComponent extends React.Component<PropFoo> { } //Notice the export default in here
}

تتفاعل:

import MyTypedComponent from "foo";

function AnotherComponent() {

   /* Since this component is default exported, no need to use the dot operator */
   return <MyTypedComponent /> 
}

لذا ، بشكل أساسي ، تحقق من الصادرات ، والتصدير الافتراضي ، والواردات وتأكد من أنك تشير بشكل صحيح.

أنا آسف جدًا على لغتي الإنجليزية وآمل أن يساعدك هذا.

بالنسبة لي كان الحل:

export type WrapperProps = {
  mainApp: React.ElementType
}

نيو ب

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات