ΠΠ΅ΡΡΠΈΡ 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.
ΠΠ΄Π΅ΡΡ ΠΎΡΡΡΡΡΡΠ²ΡΠ΅Ρ ΠΎΡΡΠ°Π»ΡΠ½Π°Ρ ΡΠ°ΡΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅, Π½ΠΎ Π΄Π»Ρ ΡΠ²Π΅ΡΠ΅Π½Π½ΠΎΡΡΠΈ ΡΠ±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ ΠΏΠΎΡΠ»Π΅Π΄Π½ΡΡ Π²Π΅ΡΡΠΈΡ @types/react
ΠΈ ΡΡΠΎ Π² Π²Π°ΡΠ΅ΠΌ node_modules ΠΈΠ»ΠΈ ΡΠ°ΠΉΠ»Π΅ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ Π½Π΅ ΠΎΡΡΠ°Π»ΠΎΡΡ Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΠΎΠ².
EDIT: Π²Ρ, Π²Π΅ΡΠΎΡΡΠ½ΠΎ, Ρ ΠΎΡΠΈΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ComponentType, Π° Π½Π΅ ReactType
@Kovensky
Π― ΡΠ±Π΅Π΄ΠΈΠ»ΡΡ, ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΡΡ Π²Π΅ΡΡΠΈΡ @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 ...
ΠΠΎΡ
ΠΎΠΆΠ΅, ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° ΡΠ²ΡΠ·Π°Π½Π° Ρ Π½ΠΎΠ²ΡΠΌΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡΠΌΠΈ "Π΄ΠΈΡΠΊΡΠΈΠΌΠΈΠ½Π°Π½ΡΠΎΠ², Π΄ΠΎΠΏΡΡΠΊΠ°ΡΡΠΈΡ
Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ NULL". ΠΠΎΡ
ΠΎΠΆΠ΅, 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>
Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ _every Π²ΡΡΡΠΎΠ΅Π½Π½ΡΡ
ΡΠ΅Π³ΠΎΠ² 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, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΎΡΠΈΠ±ΠΊΠ° Β«index not foundΒ», ΠΊΠΎΡΠΎΡΡΡ ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΠ» Π²ΡΠ΄Π°ΡΡ, Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π»Π°.
ΠΡΠ° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π±ΡΠ»Π° ΠΎΡΠΌΠ΅ΡΠ΅Π½Π° ΠΊΠ°ΠΊ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΠ°ΡΡΡ, ΠΈ Π·Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π΄Π΅Π½Ρ ΠΏΠΎ Π½Π΅ΠΉ Π½Π΅ Π±ΡΠ»ΠΎ Π½ΠΈΠΊΠ°ΠΊΠΈΡ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ. ΠΠ½ Π±ΡΠ» Π·Π°ΠΊΡΡΡ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π²Π΅Π΄Π΅Π½ΠΈΡ Ρ ΠΎΠ·ΡΠΉΡΡΠ²Π°.
ΠΠΎΠ·Π½ΠΈΠΊΠ»Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠ²ΡΠ·Π°Π½Π°. Π£ ΠΌΠ΅Π½Ρ Π΅ΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ:
function MaybeLabel(props: { useLabel: boolean }) {
const { useLabel } = props;
const TagName = useLabel ? 'label' : 'div';
return <TagName>Woookie</TagName>
}
ΡΡΠΎ ΠΏΡΠΈΠ²ΠΎΠ΄ΠΈΡ ΠΊ
error TS2604: JSX element type 'TagName' does
not 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 / react ΠΈ @ types / react-dom, ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΈΠ» ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π² ΠΌΠ°ΡΠΈΠ½ΠΎΠΏΠΈΡΠ½ΡΡ ΡΠ΅ΠΊΡΡΠ°Ρ 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
Π― ΠΏΠΎΠ»ΡΡΠΈΠ» ΡΡΡ ΠΎΡΠΈΠ±ΠΊΡ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Ρ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°Π» default, Π½ΠΎ ΠΎΠ±ΡΡΠ²ΠΈΠ» ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΡΠΊΡΠΏΠΎΡΡ ΠΊΠ°ΠΊ named Π²ΠΌΠ΅ΡΡΠΎ default Π² ΡΠ°ΠΉΠ»Π΅ .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 / response Π²Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΠ»ΠΈ?
@ericmasiello
ΠΡΡΡΠΎ! ΠΠ°ΠΊΡΡ Π²Π΅ΡΡΠΈΡ Typescript ΠΈ ΠΊΠ°ΠΊΡΡ Π²Π΅ΡΡΠΈΡ @ types / response Π²Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΠ»ΠΈ?
[email protected]
@ ΡΠΈΠΏΡ / [email protected]
Π― ΡΠ΅ΡΠΈΠ» ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, Π²ΡΠΏΠΎΠ»Π½ΠΈΠ² ΠΎΠ΄Π½ΠΎ ΠΈΠ· ΡΡΠΈΡ Π΄Π²ΡΡ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ:
.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_. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠΌ ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ, Π½ΠΎ Ρ ΠΏΠΎΡΡΠ°ΡΠΈΠ» ΠΊΡΡΡ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, ΠΊΠΎΠ³Π΄Π° Π²ΡΠ΅, ΡΡΠΎ ΠΌΠ½Π΅ Π½ΡΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ, ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡ ΡΠΎΡΠΊΠΈ ΠΏΡΠΈ ΠΈΠΌΠΏΠΎΡΡΠ΅ ΠΈ ΡΡΡΠ»Π°ΡΡΡΡ Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ.
.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 }
niu b
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
Π΄Π»Ρ ΠΌΠ΅Π½Ρ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π±ΡΠ»ΠΎ: