Versi TypeScript: 3.2.0-rc, 3.2.1
Kode
import * as React from "react";
import { Component, ReactType} from "react";
function App(props:{component:ReactType}) {
const Comp: ReactType = props.component
return (<Comp />)
}
Perilaku yang diharapkan:
Harus menghasilkan keluaran normal sebagai TypeScript 3.1.6
Perilaku sebenarnya:
TS2604: JSX element type 'Comp' does not have any construct or call signatures.
Ini menghilangkan sisa pesan kesalahan tetapi, untuk memastikan, pastikan Anda menggunakan versi terbaru @types/react
dan tidak ada duplikatnya yang tertinggal di node_modules atau file kunci Anda.
EDIT: Anda mungkin bermaksud menggunakan ComponentType dan bukan ReactType
@Bayu_joo
Saya telah memastikan menggunakan @types/react 16.7.7
dan tidak ada duplikat @types/react
di yarn.lock
.
Jika masalah terjadi karena duplikasi @types/react
, itu akan mengembalikan kesalahan Duplication of definition ...
.
Saya kembali ke "typescript": "^3.1.6"
lalu berfungsi normal.
Ketikan 3.2.1
contoh lainnya
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 ...
Sepertinya, masalah ini terkait dengan perubahan "diskriminan nullable" baru. Sepertinya ts tidak dapat menemukan antarmuka umum untuk jenis tersebut.
Contoh lainnya
interface P1 {
p?: any
c?: string // remove this and it's ok
}
interface P2 {
p?: boolean
}
Kami memiliki masalah serupa, contoh singkat:
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
Saya melihat perilaku ini sama sekali tidak valid, karena A
dan B
memiliki tipe yang sama . Pada saat yang sama, B
dan D
memiliki _type serupa_, tetapi D
tidak dapat dialihkan 🤔
Kode dalam repo: https://github.com/layershifter/ts-issue
Mereka tidak melakukannya, karena Anda menggunakan const
. Jenis A
adalah typeof configEmpty.ElementType
, tetapi jenis B
adalah 'div'
. Menggunakan let
s akan menunjukkan perilaku yang sama pada keduanya.
@Kovens bagaimana dengan A
dan C
? Mengapa C
berfungsi sementara A
gagal dengan kesalahan does not have any construct
?
Itu karena saya meningkatkan tipe ReactType
untuk mengecualikan komponen yang tidak dapat menerima props yang Anda berikan. Karena tidak ada elemen DOM yang dapat menerima { a: string | undefined }
, mereka semua dikecualikan, dan hanya komponen fungsi / kelas yang masih diperbolehkan untuk ditugaskan padanya.
@Kovens, terima kasih 👍 Sekarang masalah dengan penugasan jelas bagi saya, tapi bagaimana dengan ini?
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
dan B
memiliki tipe yang didefinisikan dengan jelas, mengapa A
gagal? Benar-benar hal yang membingungkan.
Saya mungkin akan mengatakan kesalahan @rexpan dan @goloveychuk mirip dengan # 28795 dan # 28768 berdasarkan konstruktor JSX bersyarat.
Hm, jadi masalahnya adalah bahwa ReactType<any>
mengembalikan gabungan _every builtin jsx tag_ (ditambah ComponentType<any>
, tapi bagian itu tidak bermasalah), dan tanda tangan untuk komponen tersebut tidak menyederhanakan (ada bukan tanda tangan yang dengan sempurna mencakup semua yang lain). Ini juga bergantung pada # 7294 untuk diperbaiki. Sisi positifnya, perubahan mendasar yang diperlukan untuk memperbaiki semua masalah JSX yang dilaporkan ini adalah sama.
Untuk konteks, kami secara efektif membuat tipe seperti ini:
declare const JsxSigs: {[K in keyof JSX.IntrinsicElements]: ((props: JSX.IntrinsicElements[K]) => JSX.Element)}[keyof JSX.IntrinsicElements];
yang akhirnya menjadi penyatuan banyak tanda tangan unik.
Sebelum saya mengubahnya menjadi gabungan dari semua tag jsx bawaan, itu adalah _just_ string | ComponentType<any>
, yang bahkan lebih buruk.
Ya, terutama karena sebelum 3.2, string
ketik tag hanya dengan diam-diam _disabled_ typechecker, karena kesalahan "indeks tidak ditemukan" yang seharusnya tidak terjadi tidak pernah terjadi.
Masalah ini telah ditandai sebagai duplikat dan tidak ada aktivitas apa pun dalam sehari terakhir. Itu telah ditutup untuk keperluan pemeliharaan rumah otomatis.
Mengalami masalah yang mungkin terkait. Saya memiliki komponen berikut:
function MaybeLabel(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'label' : 'div';
return <TagName>Woookie</TagName>
}
yang mengakibatkan
error TS2604: JSX element type 'TagName' does
bukan have any construct or call signatures.
sementara
function MaybeLabel2(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'span' : 'div';
return <TagName>Woookie</TagName>
}
sepenuhnya dapat diterima oleh penyusun skrip ketikan. Dengan adanya:
export function MaybeLabel3(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'label' : 'div';
return React.createElement(TagName, 'Wookie')
}
Di mana satu-satunya perbedaan dalam MaybeLabel2
adalah bahwa saya menggunakan span
daripada label
(menggunakan span
bukan div
juga tampaknya dapat diterima ). MaybeLabel3
membuatnya lebih aneh, karena seharusnya itulah yang dikompilasi MaybeLabel
.
Menggunakan versi terbaru @ types / react dan @ types / react-dom, dan memverifikasi masalah di skrip ketikan 3.2.1, 3.2.2, dan 3.3.0-dev.20181219. Di 3.1.6 semuanya berfungsi seperti yang diharapkan (tidak ada contoh yang menghasilkan kesalahan)
bagi saya solusinya adalah:
export type WrapperProps = {
mainApp: React.ElementType
}
@ TacBS tolong
Saya mungkin telah salah memahami utasnya, tetapi saya ingin meneruskan referensi ke Elemen jsx ke elemen jsx lain:
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>)
});
Bersama dengan:
export type WrapperProps = {
mainApp: React.ElementType<{prop1:string}>
}
@ TacB0sS Bagi saya trik utama adalah menambahkan kondisi if
. Sepertinya tidak masalah apakah Anda menggunakan React.ComponentType
atau React.ElementType
Saya tidak yakin saya memahami hasil dari ini. Saya memiliki kesalahan serupa yang belum dapat saya atasi. Ini kasus penggunaan saya:
// 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 }}
/>
);
};
dan kemudian saya menggunakannya seperti di komponen lain seperti:
const Header: React.SFC<{}> = () => {
return (
<div>
<Logo tag="h1" aria-label="Syn By Design: Eric Masiello's Portfolio" />
Header online
</div>
);
};
Ketika saya menjalankan kompiler, saya mendapatkan kesalahan ini:
components/Logo.tsx:13:6 - error TS2604: JSX element type 'Tag' does not have any construct or call signatures.
13 <Tag
~~~
Found 1 error.
Ada ide bagaimana membuat ini bekerja?
Alih-alih Component
, gunakan ComponentClass
Saya mendapat kesalahan ini karena saya mengimpor default tetapi menyatakan ekspor yang sesuai sebagai bernama alih-alih default di file .d.ts
... membingungkan saya untuk sementara
Hanya ingin menambahkan ini di sini. Tidak yakin apakah ini sudah dikatakan tetapi jika Anda melakukan komponen urutan hirer Anda ingin menggunakan tipe React.ComponentType
. " https://flow.org/en/docs/react/types/#toc -react-componenttype"
@ericmasiello Saya akhirnya menggunakan React.ElementType
untuk komponen yang diteruskan secara dinamis. Kasus penggunaan saya pada dasarnya adalah sebagai berikut:
type Props = {
heading: React.ElementType
}
const Header: FC<Props> = props => {
const Header = props.heading ?? 'h2';
return (
<Header className="some-class"><children /></Header>
)
}
@ericmasiello Saya akhirnya menggunakan
React.ElementType
untuk komponen yang diteruskan secara dinamis. Kasus penggunaan saya pada dasarnya adalah sebagai berikut:type Props = { heading: React.ElementType } const Header: FC<Props> = props => { const Header = props.heading ?? 'h2'; return ( <Header className="some-class"><children /></Header> ) }
Keren! Versi Typecript apa dan versi @ types / react apa yang telah Anda instal?
@rumahsakitotak
Keren! Versi Typecript apa dan versi @ types / react apa yang telah Anda instal?
[email protected]
@ types / [email protected]
Saya memecahkan masalah ini dengan melakukan salah satu dari dua hal ini:
file .d.ts:
declare module "foo" {
interface PropFoo {
propy: string;
}
class MyTypedComponent extends React.Component<PropFoo> { }
}
Reaksi:
import MyTypedComponent from "foo";
function AnotherComponent() {
/* Notice in here we have to use the dot operator and reference the component */
return <MyTypedComponent.MyTypedComponent />
}
Perhatikan bahwa, untuk menggunakan komponen yang baru diketik, kita harus menulis _MyTypedComponent.MyTypedComponent_. Ini mungkin jelas bagi sebagian orang, tetapi saya menyia-nyiakan banyak waktu ketika yang harus saya lakukan hanyalah menggunakan operator titik untuk mengimpor dan mereferensikan komponen.
file .d.ts:
declare module "foo" {
interface PropFoo {
propy: string;
}
export default class MyTypedComponent extends React.Component<PropFoo> { } //Notice the export default in here
}
Reaksi:
import MyTypedComponent from "foo";
function AnotherComponent() {
/* Since this component is default exported, no need to use the dot operator */
return <MyTypedComponent />
}
Jadi, pada dasarnya, periksa ekspor Anda, ekspor default, dan impor Anda dan pastikan Anda merujuk dengan benar.
Saya sangat menyesal atas bahasa Inggris saya dan saya harap ini membantu.
bagi saya solusinya adalah:
export type WrapperProps = { mainApp: React.ElementType }
niu b
Komentar yang paling membantu
bagi saya solusinya adalah: