@types/xxxx
dan mengalami masalah.Definitions by:
di index.d.ts
) agar mereka dapat menanggapi.Halo! Saya baru saja memperbarui ke 5.0.16
dan segera mengalami beberapa masalah menggunakan pengetikan baru ini di proyek saya yang sudah ada. Berikut adalah beberapa nomor versi yang relevan:
@types/react-redux: ^5.0.16,
typescript: ^2.8.x,
react-redux: ^5.0.5,
Berikut adalah beberapa kode yang menurut saya harus dikompilasi (dan yang dikompilasi sebelum 5.0.16
dan yang dikompilasi lagi jika kita mengatur versi kembali ke 5.0.15
):
// components/exampleComponent.ts
import React = require('react')
import { IState, IDateRange, ReportType } from '../../types/index'
export interface IExampleProps {
label?: string
dateRange: IDateRange
onDateRangeChange: (value: IDateRange) => void
}
export class ExampleComponent extends React.Component<IExampleProps> {
// implementation
}
// containers/exampleComponent.ts
import { connect } from 'react-redux'
import { IState, IDateRange, ReportType } from '../../types/index'
interface IPropsFromState {
dateRange: IDateRange
}
interface IPropsFromParent {
reportType: ReportType
}
const mapStateToProps = (state: IState, props: IPropsFromParent): IPropsFromState => {
const config = state.reporting.reportConfigs[props.reportType]
return {
dateRange: config ? config.dateRange : null,
}
}
const connector = connect<IPropsFromState, null, IPropsFromParent>(
mapStateToProps,
)
export const ExampleContainer = connector(ExampleComponent) // <-- this does not compile
Biasanya saya akan terus menggunakan wadah seperti ini,
<ExampleContainer reportType={ReportType.USERS_CREATED} />
Namun, dengan kode ini, menggunakan @types/react-redux
di 5.0.16
dan TypeScript di 2.8.1
Saya malah mendapatkan kesalahan berikut:
[ts]
Argument of type 'typeof ExampleComponent' is not assignable to parameter of type 'ComponentType<IPropsFromState & DispatchProp<any> & IPropsFromParent>'.
Type 'typeof ExampleComponent' is not assignable to type 'StatelessComponent<IPropsFromState & DispatchProp<any> & IPropsFromParent>'.
Type 'typeof ExampleComponent' provides no match for the signature '(props: IPropsFromState & DispatchProp<any> & IPropsFromParent & { children?: ReactNode; }, context?: any): ReactElement<any>'.
Memeriksa perubahan yang diperkenalkan di 5.0.16
, rasanya sistem tipenya kesal karena connector
memiliki tipe InferableComponentEnhancerWithProps<IPropsFromState & IPropsFromParent, IPropsFromParent>
yang berarti mengharapkan argumen pertama bertipe IPropsFromState & IPropsFromParent
. Komponen dasar saya tidak memiliki properti reportType
.
Misalnya, jika saya menulis ini:
const f = <P extends IPropsFromParent & IPropsFromState>(component: Component<P>) => { /**/ }
const g = <P extends IPropsFromParent & IPropsFromState>(props: P) => { /**/ }
const record: IExampleProps = null
f(ExampleComponent)
g(record)
Contoh minimal ini gagal. Yang pertama gagal karena alasan yang sama seperti kode di atas, dengan pesan kesalahan buram yang sama. Yang kedua gagal karena, jelas, IExampleProps
tidak memiliki properti reportType: ReportType
sehingga kami tidak dapat menetapkan IExampleProps
ke P
. Itu hilang reportType
. Saya menduga ini, di bawah tenda, apa yang menyebabkan contoh pertama gagal.
Sepertinya setelah 5.0.16
container tidak diizinkan untuk menambahkan properti baru ke antarmuka komponen yang dibungkusnya? Inilah yang saya lihat, melihat kodenya.
Ini adalah bagian dari alur kerja normal saya untuk mendefinisikan komponen hanya dalam hal properti apa yang mereka butuhkan, dan kemudian memperluas komponen tersebut dengan HOC yang mendefinisikan antarmuka baru dan menyediakan komponen propertinya melalui redux store. Dalam beberapa kasus, antarmuka baru adalah bagian dari antarmuka komponen yang dibungkus, tetapi dalam kasus lain mungkin tidak. Dalam kasus di atas, antarmuka baru memiliki properti tambahan reportType
yang akan digunakan pemanggil tetapi komponen yang dibungkus tidak akan pernah dilihat.
Saya memiliki contoh lain dari teknik yang saya gunakan yang rusak oleh perubahan ini:
Misalkan kita memiliki dua komponen sederhana,
class NameDateComponent extends React.PureComponent<{ name: string, date: string}> {}
class DateOnlyComponent extends React.PureComponent<{ date: string }> {}
Saya ingin membangun HOC yang menyediakan date
untuk komponen ini tanpa perlu mengetahui apa pun tentang properti name
sama sekali. Dengan cara ini saya dapat membuat, misalnya, NameProvider dan DateProvider, dan menyusunnya seperti ini: NameProvider(DateProvider(BaseComponent))
atau seperti ini DateProvider(NameProvider(BaseComponent))
, sesuatu yang biasanya tidak dapat saya lakukan dengan komponen yang diketik dengan baik penambah karena kebutuhan untuk menentukan TOwnProps
.
interface IWithDate {
date: string
}
// ComponenProps defines a component interface that includes IWithDate
// NewAPI defines a new interface that excludes IWithDate
// so the types represent only what will change in the given component, without needing to know the rest of the interface
function DateProvider <ComponentProps extends IWithDate, NewAPI extends Minus<ComponentProps, IWithDate>> (Base: CompositeComponent<ComponentProps>) {
const enhancer = connect<ComponentProps, null, NewAPI>(
(_state: IState, props: NewAPI): ComponentProps => {
// because of the 'never' type,
// typescript doesn't think NewAPI & IWithProps == ComponentProps
// so we have to coerce this (but you and I can see that the above holds)
const newProps: any = Object.assign({
date: '2017-01-01'
}, props)
return newProps as ComponentProps
},
null
)
return enhancer(Base) // <-- after 5.0.16 this line does not compile
}
Penambah komponen agnostik antarmuka baru ini digunakan sebagai berikut:
const NameOnly = DateProvider(NameDateComponent)
const Nothing = DateProvider(DateOnlyComponent)
.
.
.
<Nothing />
<NameOnly name='Bob' />
<NameDateComponent name='Bob' date='2017-01-01' />
Jadi DateProvider
HOC dapat menambah komponen tanpa sepenuhnya menyadari antarmuka komponen itu. Hanya perlu diketahui bahwa komponen yang diberikan akan mampu menerima alat peraga yang disediakannya.
Dengan 5.0.16
ini tidak lagi berfungsi, sebagai gantinya saya mendapatkan pesan kesalahan berikut:
[ts]
Argument of type 'CompositeComponent<ComponentProps>' is not assignable to parameter of type 'ComponentType<ComponentProps & NewAPI>'.
Type 'ComponentClass<ComponentProps>' is not assignable to type 'ComponentType<ComponentProps & NewAPI>'.
Type 'ComponentClass<ComponentProps>' is not assignable to type 'StatelessComponent<ComponentProps & NewAPI>'.
Types of property 'propTypes' are incompatible.
Type 'ValidationMap<ComponentProps>' is not assignable to type 'ValidationMap<ComponentProps & NewAPI>'.
Type 'keyof ComponentProps | keyof NewAPI' is not assignable to type 'keyof ComponentProps'.
Type 'keyof NewAPI' is not assignable to type 'keyof ComponentProps'.
Type 'keyof NewAPI' is not assignable to type '"date"'.
Bermain-main, saya perhatikan yang berikut:
interface IWithDate {
date: string
}
interface IComponentProps {
name: string
date: string
}
// I've torn out the internals of the DateProvider above
const connect1 = <T extends IWithDate, U extends Omit<T, keyof IWithDate>>(base: CompositeComponent<T>) => {
const enhancer: InferableComponentEnhancerWithProps<T & U, U> = () => null
return enhancer(base) // <-- this is a compile error
}
const connect2 = <T extends IWithDate, U extends Omit<T, keyof IWithDate>>() => {
const enhancer: InferableComponentEnhancerWithProps<T & U, U> = () => null
return enhancer
}
const enhancer = connect2<IComponentProps, Omit<IComponentProps, keyof IWithDate>>()
const container = enhancer(NameDateComponent) // <-- this is not a compile error
Ketika kami secara eksplisit mengetik konektor, semuanya berfungsi?
Itu dia! Terima kasih telah membaca ;) untuk saat ini saya telah mengatur @types/react-redux
ke versi sebelumnya dan semuanya baik-baik saja.
@variousauthors bisakah Anda membagikan versi @types/react
dan @types/react-redux
Anda gunakan?
EDIT: @
mengacaukan banyak hal karena nama lib tidak muncul, maaf :kecewa:
@variousauthors Saya pikir Anda tepat dengan komentar ini
Sepertinya setelah 5.0.16 wadah tidak diizinkan untuk menambahkan properti baru ke antarmuka komponen yang dibungkusnya? Inilah yang saya lihat, melihat kodenya.
Bugnya adalah definisi tipe untuk fungsi connect
redux berpotongan ownProps
dan mapPropsToState
. Ini berarti bahwa setiap komponen "wadah" dipaksa untuk memiliki alat peraga yang direplikasi dalam komponen "presentasional" yang diturunkan - yang merusak pola desain redux yang umum.
PR yang diperkenalkan: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24764
Masalah lain: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24922
Mengembalikan ke 5.0.15 tidak sepenuhnya menyelesaikan masalah. Sementara 5.0.15 akan mengkompilasi kode semacam ini tanpa peringatan- masih error jika Anda menambahkan pemeriksaan tipe props untuk komponen presentasi dalam panggilan connect
. (Dengan asumsi komponen pembungkus Anda memiliki prop yang MyComponent
tidak)
Misalnya ini akan berfungsi di 5.0.15, tetapi tidak 5.0.16
connect(stateToProps, dispatchToProps)(MyComponent)
Namun- bahkan di 5.0.15, Anda tidak dapat memeriksa properti MyComponent
tanpa kesalahan kompiler
connect<statetoprops, dispatchtoprops, mycomponentprops)(stateToProps, dispatchToProps)(MyComponent)
Ini akan menjadi kesalahan yang mengeluh bahwa prop komponen pembungkus tidak ada di MyComponent
Saya pikir ini adalah masalah yang lebih besar yang telah mengintai dalam pemetaan tipe yang dibawa oleh pembersihan @Pajn .
Komentar yang paling membantu
Mengembalikan ke 5.0.15 tidak sepenuhnya menyelesaikan masalah. Sementara 5.0.15 akan mengkompilasi kode semacam ini tanpa peringatan- masih error jika Anda menambahkan pemeriksaan tipe props untuk komponen presentasi dalam panggilan
connect
. (Dengan asumsi komponen pembungkus Anda memiliki prop yangMyComponent
tidak)Misalnya ini akan berfungsi di 5.0.15, tetapi tidak 5.0.16
connect(stateToProps, dispatchToProps)(MyComponent)
Namun- bahkan di 5.0.15, Anda tidak dapat memeriksa properti
MyComponent
tanpa kesalahan kompilerconnect<statetoprops, dispatchtoprops, mycomponentprops)(stateToProps, dispatchToProps)(MyComponent)
Ini akan menjadi kesalahan yang mengeluh bahwa prop komponen pembungkus tidak ada di
MyComponent
Saya pikir ini adalah masalah yang lebih besar yang telah mengintai dalam pemetaan tipe yang dibawa oleh pembersihan @Pajn .