Definitelytyped: Beberapa panggilan terhubung yang ada terputus oleh 5.0.16

Dibuat pada 11 Apr 2018  ·  3Komentar  ·  Sumber: DefinitelyTyped/DefinitelyTyped

  • [x] Saya mencoba menggunakan paket @types/xxxx dan mengalami masalah.
  • [x] Saya mencoba menggunakan tsc versi stabil terbaru. https://www.npmjs.com/package/typescript
  • [x] Saya punya pertanyaan yang tidak pantas untuk StackOverflow . (Silakan ajukan pertanyaan yang sesuai di sana).
  • [x] [Sebutkan](https://github.com/blog/821-mention-somebody-they-re-notified) penulisnya (lihat Definitions by: di index.d.ts ) agar mereka dapat menanggapi.

    • Penulis: @Pajn @tkqubo @thasner @kenzierocks @clayne11 @tansongyang @NicholasBoll @mDibyo @pdeva

Masalah

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,

Wadah Khas tidak Dikompilasi

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.


Wadah yang Lebih Idiosyncratic tidak Dikompilasi

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.

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 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 .

Semua 3 komentar

@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 .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

Zzzen picture Zzzen  ·  3Komentar

jbreckmckye picture jbreckmckye  ·  3Komentar

jgoz picture jgoz  ·  3Komentar

fasatrix picture fasatrix  ·  3Komentar

csharpner picture csharpner  ·  3Komentar