Definitelytyped: تم كسر بعض مكالمات الاتصال الحالية بنسبة 5.0.16

تم إنشاؤها على ١١ أبريل ٢٠١٨  ·  3تعليقات  ·  مصدر: DefinitelyTyped/DefinitelyTyped

  • [x] حاولت استخدام الحزمة @types/xxxx وواجهت مشاكل.
  • [x] حاولت استخدام أحدث إصدار مستقر من tsc. https://www.npmjs.com/package/typescript
  • [x] لدي سؤال غير مناسب لـ StackOverflow . (يرجى طرح أي أسئلة مناسبة هناك).
  • [x] [أذكر] (https://github.com/blog/821-mention-somebody-they-re-notified) المؤلفون (انظر Definitions by: في index.d.ts ) حتى يتمكنوا من ذلك رد.

    • المؤلف:Pajntkqubothasnerkenzierocks @ clayne11tansongyangNicholasBollmDibyopdeva

القضايا)

أهلا! لقد قمت للتو بالتحديث إلى 5.0.16 وواجهت على الفور بعض المشاكل في استخدام هذه الأنواع الجديدة في مشروعي الحالي. فيما يلي بعض أرقام الإصدارات ذات الصلة:

@types/react-redux: ^5.0.16,
typescript: ^2.8.x,
react-redux: ^5.0.5,

لا يتم تجميع الحاوية النموذجية

في ما يلي بعض التعليمات البرمجية التي أعتقد أنه يجب تجميعها (والتي تم تجميعها قبل 5.0.16 والتي يتم تجميعها مرة أخرى إذا قمنا بتعيين الإصدار مرة أخرى إلى 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

عادةً ما أستمر في استخدام الحاوية مثل هذا ،

<ExampleContainer reportType={ReportType.USERS_CREATED} />

ومع ذلك ، باستخدام هذا الرمز ، باستخدام أحدث @types/react-redux بسعر 5.0.16 ونسخه على 2.8.1 ، أحصل على الخطأ التالي بدلاً من ذلك:

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

عند فحص التغييرات التي تم إدخالها في 5.0.16 ، يبدو أن نظام الكتابة مضطرب لأن connector يحتوي على InferableComponentEnhancerWithProps<IPropsFromState & IPropsFromParent, IPropsFromParent> مما يعني أنه يتوقع أن تكون الوسيطة الأولى من النوع IPropsFromState & IPropsFromParent . المكون الأساسي الخاص بي يفتقد الخاصية reportType .

على سبيل المثال ، إذا كتبت هذا:

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)

هذه الأمثلة البسيطة تفشل. فشل الأول لنفس سبب الكود أعلاه ، مع نفس رسالة الخطأ غير الشفافة. فشل الثاني لأنه من الواضح أن IExampleProps ليس لديه خاصية reportType: ReportType لذلك لا يمكننا تعيين IExampleProps إلى P . ينقصه reportType . أظن أن هذا ، تحت الغطاء ، هو سبب فشل المثال الأول.

يبدو أنه بعد 5.0.16 لا يُسمح للحاويات بإضافة خصائص جديدة إلى واجهات مكوناتها المغلفة؟ هذا ما أراه ، بالنظر إلى الكود.

يعد تحديد المكونات جزءًا من سير العمل العادي الخاص بي من حيث الخصائص التي يحتاجون إليها فقط ، ثم توسيع هذه المكونات باستخدام المكوّنات ذات الترتيب الأعلى التي تحدد واجهة جديدة وتوفر للمكون خصائصه عبر متجر redux. في بعض الحالات ، تكون الواجهة الجديدة عبارة عن مجموعة فرعية من واجهة المكون المغلف ، ولكن في حالات أخرى قد لا تكون كذلك. في الحالة المذكورة أعلاه ، تحتوي الواجهة الجديدة على خاصية إضافية reportType سيستخدمها المتصل ولكن لن يراها المكون المغلف أبدًا.


لا يتم تجميع "الحاوية الأكثر خصوصية"

لدي مثال آخر على الأسلوب الذي أستخدمه والذي كسره هذا التغيير:

لنفترض أن لدينا عنصرين بسيطين ،

class NameDateComponent extends React.PureComponent<{ name: string, date: string}> {}

class DateOnlyComponent extends React.PureComponent<{ date: string }> {}

أريد إنشاء HOC يوفر date لهذه المكونات دون الحاجة إلى معرفة أي شيء عن الخاصية name على الإطلاق. بهذه الطريقة يمكنني ، على سبيل المثال ، إنشاء NameProvider و DateProvider ، وتأليفهما على النحو التالي: NameProvider(DateProvider(BaseComponent)) أو مثل هذا DateProvider(NameProvider(BaseComponent)) ، وهو شيء لا يمكنني فعله عادةً باستخدام مكون مكتوب جيدًا محسن بسبب الحاجة إلى تحديد 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
}

يتم استخدام مُحسِّن المكون المحايد الجديد للواجهة على النحو التالي:

const NameOnly = DateProvider(NameDateComponent)
const Nothing = DateProvider(DateOnlyComponent)

.
.
.

<Nothing />
<NameOnly name='Bob' />
<NameDateComponent name='Bob' date='2017-01-01' />

لذا فإن DateProvider HOC قادر على زيادة أحد المكونات دون أن يكون على دراية كاملة بواجهة هذا المكون. يحتاج فقط إلى معرفة أن المكون المحدد سيكون قادرًا على قبول الدعائم التي يوفرها.

مع 5.0.16 لم يعد هذا يعمل ، وبدلاً من ذلك تظهر لي رسالة الخطأ التالية:

[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"'.

أثناء اللعب ، لاحظت ما يلي:

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

عندما نكتب الموصل بشكل صريح ، كل شيء يعمل؟


هذا كل شيء! شكرًا على القراءة ؛) في الوقت الحالي ، قمت بتعيين @types/react-redux إلى إصدار سابق وكل شيء على ما يرام.

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

العودة إلى 5.0.15 لا يحل تماما هذه المسألة. بينما سيقوم 5.0.15 بتجميع هذا النوع من التعليمات البرمجية دون سابق إنذار ، إلا أنه لا يزال هناك أخطاء إذا قمت بإضافة التحقق من النوع للعناصر الخاصة بمكوِّن العرض في المكالمة connect . (بافتراض أن مكون الالتفاف الخاص بك يحتوي على خاصية لا تمتلكها MyComponent )

على سبيل المثال ، سيعمل هذا في الإصدار 5.0.15 ، ولكن ليس 5.0.16
connect(stateToProps, dispatchToProps)(MyComponent)

ومع ذلك ، حتى في الإصدار 5.0.15 ، لا يمكنك كتابة تحديد العناصر MyComponent بدون خطأ في المترجم
connect<statetoprops, dispatchtoprops, mycomponentprops)(stateToProps, dispatchToProps)(MyComponent)
سيحدث هذا خطأ عند الشكوى من عدم وجود خاصية مكونات الالتفاف في MyComponent

أعتقد أن هذه مشكلة أكبر كانت كامنة في تعيينات النوع التي سلطت عملية تنظيف

ال 3 كومينتر

variousauthors هل يمكنك مشاركة إصدارات @types/react و @types/react-redux التي تستخدمها؟

تحرير: @ أفسد الأشياء ولم تظهر أسماء libs ، آسف: خائب الأمل:

variousauthors أعتقد أنك

يبدو أنه بعد 5.0.16 لا يُسمح للحاويات بإضافة خصائص جديدة إلى واجهات مكوناتها المغلفة؟ هذا ما أراه ، بالنظر إلى الكود.

الخطأ هو أن تعريفات النوع لوظيفة redux connect تتقاطع مع ownProps و mapPropsToState . هذا يعني أن أي مكون "حاوية" مجبر على نسخ الدعائم الخاصة به في أي مكونات "عرضية" مشتقة - والتي تكسر أنماط تصميم الإعادة الشائعة.

العلاقات العامة التي قدمت: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24764
مشكلة أخرى: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24922

العودة إلى 5.0.15 لا يحل تماما هذه المسألة. بينما سيقوم 5.0.15 بتجميع هذا النوع من التعليمات البرمجية دون سابق إنذار ، إلا أنه لا يزال هناك أخطاء إذا قمت بإضافة التحقق من النوع للعناصر الخاصة بمكوِّن العرض في المكالمة connect . (بافتراض أن مكون الالتفاف الخاص بك يحتوي على خاصية لا تمتلكها MyComponent )

على سبيل المثال ، سيعمل هذا في الإصدار 5.0.15 ، ولكن ليس 5.0.16
connect(stateToProps, dispatchToProps)(MyComponent)

ومع ذلك ، حتى في الإصدار 5.0.15 ، لا يمكنك كتابة تحديد العناصر MyComponent بدون خطأ في المترجم
connect<statetoprops, dispatchtoprops, mycomponentprops)(stateToProps, dispatchToProps)(MyComponent)
سيحدث هذا خطأ عند الشكوى من عدم وجود خاصية مكونات الالتفاف في MyComponent

أعتقد أن هذه مشكلة أكبر كانت كامنة في تعيينات النوع التي سلطت عملية تنظيف

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