Definitelytyped: Masalah dengan connect() di @types/react-redux diperkenalkan di 4.4.41

Dibuat pada 6 Jun 2017  ·  44Komentar  ·  Sumber: DefinitelyTyped/DefinitelyTyped

Menggunakan @types/react-redux versi 4.4.40, kode berikut

import * as React from 'react';
import {connect} from "react-redux";

interface State {
    y: number;
}

// Own properties
interface OP {
    x: number;
}

// State properties
interface SP {
    y: number;
}

function mapStateToProps(state: State, ownProps: OP): OP & SP {
    return {
        x: ownProps.x,
        y: state.y,
    };
}

class TestComp extends React.Component<OP & SP, null> {
    render() {
        return <p>Hello</p>;
    }
}

export default connect(mapStateToProps)(TestComp);

akan membiarkan saya menggunakan TestComp sebagai berikut:

const tc = <TestComp x={42}/>;

Dengan versi 4.4.41 dan 4.4.42 di atas menyebabkan kesalahan kompilasi berikut:

error TS2324: Property 'y' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<OP & SP, ComponentState>> & { children?:...'.

/cc @thasner @seansfkelley @tkqubo @blakeembrey @sandersn @mhegazy @andy-ms @hans-permana

Komentar yang paling membantu

Rusak lagi di TypeScript 3.0.1. Hai Thien!

Semua 44 komentar

Saya mendapatkan kesalahan ini juga. Rasanya seperti salah satu typedefs secara tidak sengaja bertukar TOwnProps dan TMergedProps / TStateProps , tetapi saya hanya melihat sekilas index.d.ts .

Setiap pembaruan tentang masalah ini? Saya pikir ini bisa menjadi showstopper bagi pengembang baru yang datang ke redux + TypeScript, terima kasih atas kerja bagus Anda.

@brauliodiez Saya menggabungkan perbaikan @blakeembrey #16969. Ini harus tersedia dalam satu jam atau lebih. Beri tahu saya jika itu membantu.

Saya pikir kami masih melihat masalah ini bahkan dengan perbaikan dari https://github.com/DefinitelyTyped/DefinitelyTyped/pull/16969. Inilah komponen dummy yang saya buat untuk mencoba dan mengisolasi masalah:

import * as React from "react"
import { connect, MapStateToProps, MapDispatchToPropsFunction } from "react-redux"


interface RootState {
  globalA: string
  globalB: number
}

interface DumbComponentProps {
  a: string
  b: number
  c?: number
}

const DumbComponent = (props: DumbComponentProps): JSX.Element => {
  return (
    <div>Something: {props.a} {props.b} {props.c}</div>
  )
}

type ConnectedStateProps = Pick<DumbComponentProps, "a" | "b">
type ConnectedOwnProps = Pick<DumbComponentProps, "c">

const mapStateToProps: MapStateToProps<ConnectedStateProps, ConnectedOwnProps> = (
    state: RootState): ConnectedStateProps => {
  return {
    a: state.globalA,
    b: state.globalB
  }
}

const SmartComponent = connect(
  mapStateToProps
)(DumbComponent)

export default SmartComponent

Saya kemudian menggunakan SmartComponent di suatu tempat dan meneruskan c (perhatikan bahwa a & b seharusnya berasal dari negara bagian).

...
return (
  <SmartComponent c{2} />
)

Kesalahan yang saya dapatkan adalah:

error TS2322: Type '{ c: 2; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<DumbComponentProps, ComponentState>> & R...'.
  Type '{ c: 2; }' is not assignable to type 'Readonly<DumbComponentProps>'.
    Property 'a' is missing in type '{ c: 2; }'.

Memeriksa tipe dalam Kode VS, saya perhatikan bahwa itu mengambil tipe yang salah untuk SmartComponent. Ia mengira itu React.ComponentClass<DumbComponentProps> ... tetapi seharusnya React.ComponentClass<Pick<DumbComponentProps, "c">> (yaitu, seharusnya hanya menerima OwnProps. Ini masuk akal dari jenisnya, di mana ComponentDecorator adalah fungsi yang mengembalikan ComponentClass<T> (di mana T extends TOwnProps ) ... jadi sayangnya saya tidak tahu mengapa itu tidak memetakan dengan benar.

Apakah saya melakukan sesuatu yang jelas salah di sini? Apakah ada cara untuk membuat kompiler menunjukkan kepada saya langkah demi langkah apa yang disimpulkannya?

Sepertinya mapDistpachToProps tidak opsional sekarang. Apakah itu baik-baik saja atau bug?

Pembaruan untuk komentar saya di atas, setelah menggali sedikit - saya telah membuat kasus uji yang saat ini gagal (tapi saya yakin tidak boleh) dan perbaikan pada pengetikan yang menangani kasus saya, tetapi tidak menangani kasus di mana ia harus menebak apa OwnProps itu (misalnya connect()(DumbComponent) ). Perubahan saya ada di sini:
https://github.com/DefinitelyTyped/DefinitelyTyped/compare/master...ritwik :react-redux/fix-ownprop-inference
Ingin membantu menyelesaikan ini, tetapi saya mencapai batas pengetahuan saya dengan TypeScript. Jika ada yang memiliki pemikiran tentang test case atau saran saya, akan senang untuk mendiskusikannya.

Hanya menutup loop di sini - https://github.com/DefinitelyTyped/DefinitelyTyped/pull/17196 sepertinya memperbaiki ini untuk basis kode kami.

Apakah ini terpecahkan? Saat ini saya mendapatkan masalah ini di ^5.0.8 ( IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick ... ). Satu-satunya perbedaan adalah saya menggunakan types alih-alih interfaces .

siapa pun? ini adalah showstoppper nyata bagi saya sayangnya ...

@proProbe Bisakah Anda memberikan versi @types/react-redux , @types/react , dan redux Anda, dan contoh yang mereproduksi kesalahan?
Juga penulis paket CC: @tkqubo @thasner @kenzierocks @clayne11 @tansongyang @nicholasboll

Maaf untuk jawaban yang terlambat! Saya sedang bekerja dengan sampel untuk mereproduksinya. Saya kemudian tiba-tiba menyadari bahwa ini telah diperbaiki di @types/react-redux: "^5.0.8". Terimakasih Meskipun!

Masih mendapatkannya dengan "^5.0.10" :(

"@types/react": "^15.6.4",
"redux": "3.7.2",
"@types/react-redux": "^5.0.10"

Saya dapat membagikan cuplikan kode dengan pembuat paket tetapi sayangnya tidak untuk publik.

Menurunkan versi ke 4.4.40 seperti yang disarankan di atas segera menghapus kesalahan.

Saya dapat menyelesaikan ini dalam basis kode saya sendiri dengan menghubungkan parameter tipe pada jenis nilai pengembalian mapStateToProps dan apa yang saya inginkan dari ownProps. Diambil di luar konteks jika saya ingin memanggil daftar produk saya dengan daftar id produk seperti:

<ProductList productIDs={productIDs} />

dan minta mapStateToProps untuk menerjemahkan id tersebut menjadi produk yang akan ditampilkan dalam daftar seperti:

const mapStateToProps = (state: RootState, ownProps: {productIDs: List<UUID>}) => {
  return { products: state.get('products').filter(
    (p: Product) => ownProps.productIDs.contains(p.uuid)) };
};

maka saya harus membuat parameter connect seperti:

const ProductList = connect<ProductListProps, void, {productIDs: List<UUID>}>(mapStateToProps)(ProductListComponent);

Setelah beberapa penyelidikan. Saya menemukan solusi sederhana. Yang hanya perlu Anda lakukan adalah memiliki "compilerOptions": { "strict": true } di tsconfig.json Anda jika Anda menghubungkan komponen React.Component<,>.

TypeScript 2.8.x memperbaikinya. Tingkatkan dan cobalah.

Rusak lagi di TypeScript 3.0.1. Hai Thien!

Melanggar dengan TypeScript 3.2.2 juga.

Apakah masalah ini memiliki pembaruan?

Pecah bagi saya dengan TypeScript 3.2.2 juga. Namun, membubuhi keterangan connect dengan connect<Props> tampaknya memperbaikinya.

Saya memiliki masalah yang sama, bahkan dengan koneksi anotasi :/

Saya memiliki masalah yang sama juga, tidak ada pembaruan sama sekali?

Melanggar dengan TypeScript 3.2.4 juga.

Sepertinya ini tidak akan segera teratasi.

Untuk semua orang yang mengalami masalah ini, pastikan Anda mengimpor komponen yang terhubung dengan benar. Saya mengganti komponen yang sudah ada untuk memiliki fungsi connect() setelah diperlukan untuk mengakses status aplikasi dari redux. Saat melakukan ini, saya beralih dari mengekspor fungsi stateless ke mengekspor komponen kelas saya sebagai default. Ketika saya tidak mengubah cara saya mengimpornya ke file lain, kesalahan ini muncul.

Ini bekerja.

Apakah ada solusi untuk setidaknya membungkam kesalahan ini secara lokal?

Sepertinya ada flip flop di suatu tempat di OwnProps versus StateProps. Saya melihat masalah ini di mana kami memiliki komponen terhubung Redux yang memiliki anak.

Yang saya lakukan untuk membungkam masalah ini adalah menggunakan <any> :

export default connect<any>(states, actions)(SomeComponent);

juga berfungsi jika Anda menggunakan tulis:

export default compose<any>(
  connect(states, actions),
  withStyles(styles)
)(SomeFunctionalComponent);

Ini akan membungkam kesalahan saat meneruskan alat peraga ke komponen 'pintar'/terhubung.

EDIT: Saya baru saja membaca ulang utasnya lagi, dan sepertinya solusi @themodernlife adalah solusi yang lebih baik (mis.

Bukankah itu juga menghancurkan semua pengecekan tipe dan Intellisense? Jadi apa gunanya menambahkan pengetikan sama sekali? @dcefram

Ya, ini solusi hanya untuk membungkam kompiler dan membiarkannya membangun untuk mencegah ini menjadi "show stopper" (atau dalam kasus saya, untuk mencegah saya menulis ulang semuanya dari TS atau terhenti sampai perbaikan keluar ). Ini bukan solusi .

Saya juga, menunggu perbaikan untuk ini :)

Solusi yang lebih baik adalah mengetikkan panggilan connect secara manual seperti ini:

type StateProps = {
  // Attributes that you want mapped from redux store
}
type DispatchProps = {
  // Dispatch actions
}
type OwnProps = {
  // Other props that component expects when being created
}
type Props = StateProps & DispatchProps & OwnProps;
class ExampleComponent extends React.Component<Props> { /* ... */ }

const mapStateToProps = (state: State, ownProps: OwnProps): StateProps => { /* .. */ }
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => { /* ... */ }

export default connect<StateProps, DispatchProps, OwnProps>
  (mapStateToProps, mapDispatchToProps)(ExampleComponent)

Ini harus membuat komponen terhubung yang benar yang mengharapkan OwnProps saat dibuat dan tidak ada props status atau pengiriman lainnya.

Negatif. Itu masih mencoba untuk menyimpulkan jenisnya. Sebagai gantinya saya harus mengganti secara manual mengetik const dan kemudian mengembalikannya sebagai default.

const connected: React.ComponentType<OwnProps> = connect<StateProps, DispatchProps, OwnProps>(......)(Component);
export default connected;

Menghadapi masalah yang sama dengan connect() menggunakan "@types/react-redux": "7.0.1" dan "typescript": "3.4.5" . Tidak ada solusi yang disebutkan yang tampaknya membantu. @TroySchmidt Bisakah Anda membagikan bagaimana Anda menggunakan "terhubung" ini di komponen induk jika memungkinkan beberapa kode contoh akan sangat membantu

Hai, saya memiliki kesalahan serupa. react-redux tampaknya tidak menyelesaikan nilai pengembalian mapStateToProps sebagai "TInjectedProps", yang menyebabkan pengecualian yang salah dalam Abaikan helper @types/react-redux index.d.ts:110 export type InferableComponentEnhancerWithProps .

definisi tipe dalam fungsi koneksi memecahkan masalah

// connect Redux
export const RCHeader = connect
<IHeaderStateToProps, //returned by mapStateToProps
 {}, // not necessary
 IHeaderProps, // props you want to pass through jsx/tsx
 IHeaderConnectedReduxStateProps, // combined from IHeaderMapStateToProps and IHeaderProps
 {}// not necessary
>(
    (state: ISettingsState ): IHeaderStateToProps => {
        return {
            headerLogoURL: state.settings.headerLogoURL
        }
    },
    undefined,
    undefined,
    { forwardRef: true }
)(Header);
{
  "dependencies": {
    "react": "^16.8.6",
    "react-redux": "^6.0.1",
    "redux": "^4.0.1"
  },
  "devDependencies": {
    "@types/react": "^16.8.17",
    "@types/react-redux": "^7.0.6",
    "react-scripts-ts": "^4.0.8",
    "typescript": "^3.4.5"
  }
}

Apakah ada pembaruan untuk ini?

Baru-baru ini, saya menulis sebuah komponen yang akan connect untuk redux. Ketika saya menggunakan komponen ini di tempat lain, semua propertinya hilang. Dan perbaiki dengan:

type StateProps = {
  /* some code */
};

type DispatchProps = {
  /* some code */
};

type OwnProps = {
  /* some code */
};

type Props = StateProps & DispatchProps & OwnProps;

const mapStateToProps = (state: IReduxState): StateProps => ({
  /* some code */
});

const mapDispatchToProps = (dispath: Dispatch<AnyAction>): DispatchProps => {
  /* some code */
};

const BaseComponent: React.FC<Props> = (props: Props) => {
  /* some code */
};

export const ConnectedComponent: React.ComponentType<OwnProps> = connect<
  StateProps,
  DispatchProps,
  OwnProps,
  IReduxState
>(
  mapStateToProps,
  mapDispatchToProps
)(BaseComponent);

dependensi di bawah ini:

{
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-redux": "^7.1.0",
    "redux": "^4.0.1",
  },
  "devDependencies": {
    "@types/react": "^16.8.22",
    "@types/react-dom": "^16.8.4",
    "@types/react-redux": "^7.1.0",
    "@types/redux": "^3.6.0",
    "typescript": "^3.5.2"
  }
}

menambahkan semua tipe itu alih-alih memiliki beberapa inferensi tipe dasar sepertinya bukan solusi yang baik bagi saya ...

Ini sepertinya masih menjadi masalah. Cukup yakin masalahnya diperkenalkan di versi 7.0.2 , karena saya dapat menginstal 7.0.1 dan mengetik inferensi berfungsi dengan benar.

Bekerja untuk saya.
@justemit memposting pendekatan yang benar yang berfungsi pada versi terakhir dari reaksi dan redux.

@justemit Terima kasih, ini membuatku gila

Sunting: Saya telah memperbaiki masalah menggunakan React.FC<Props>

Saya pikir masalah ini masih hidup dan sehat di @types/react-redux@^7.1.2 :

const propTypes = {
  foo: PropTypes.number.isRequired,
  bar: PropTypes.func.isRequired
};

// inferring the Props type
interface Props extends PropTypes.InferProps<typeof propTypes> {}
// although doing it explicitly also yields the same result
interface Props {
  foo: number,
  bar: (...args: any[]) => any
}

const Foo = (props : Props) => <></> // EDIT: incorrect way to define functional components
const Foo : React.FC<Props> = (props) => <></> // EDIT: the correct way
//          ^^^^^^^^

Foo.propTypes = propTypes;
/* Foo.defaultProps = {
  foo: 1,
  bar: () => {}
} //*/

const mapStateToProps = (state : any) => ({
  foo: 1
})
const mapDispatchToProps = {
  bar: () => {}
}
const Bar = connect(mapStateToProps, mapDispatchToProps)(Foo)

const Baz = () => <Bar /> // throws an error
Type '{}' is missing the following properties from type 'Readonly<Pick<Pick<Props, never>, never> & Pick<InferProps<{ foo: Validator<number>; bar: Validator<(...args: any[]) => any>; }>, "foo" | "bar">>': foo, bar



md5-e744aa0bac3ac7f45f015259c5597ea9



Jenis 'ConnectedComponentClass<...>' tidak dapat ditetapkan untuk mengetik 'ComponentType<{}>'.
Jenis 'Readonly<{}>' tidak memiliki properti berikut dari jenis 'Readonly; bar: Validator<(...args: any[]) => any>; }>>': foo, bar

And even if typing everything explicitly helped, I agree with <strong i="16">@alexandrudanpop</strong> that it should be possible to infer those types instead of doing everything manually 🤔 

**Edit:** for anyone looking for inspiration for a workaround, I currently resort to explicitly casting using `unknown`:
```ts
// assumes `mapDispatchToProps` is an object, could be a function if used with `ReturnType`
type OwnProps = Omit<Props, keyof ReturnType<typeof mapStateToProps> | keyof mapDispatchToProps>
connect(mapStateToProps, mapDispatchToProps)(Foo) as unknown as React.ComponentType<OwnProps>

Sesuatu yang mungkin membantu dengan inferensi (masih beberapa pekerjaan manual) melakukan sesuatu seperti ini
Keluar dari contoh @kdmadej

type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatchToProps;
type OwnProps = {
  a: string;
  b: number;
}

type Props = StateProps & DispatchProps & OwnProps;

const Foo = (props : Props) => <></>

const mapStateToProps = (state : any) => ({
  foo: 1
})

const mapDispatchToProps = {
  bar: () => {}
}

export default connect(mapStateToProps, mapDispatchToProps)(Foo)


// In another file
const Baz = () => <Bar /> <-- this should throw error expecting `a` and `b`

Masalah yang saya hadapi bagaimanapun, adalah ketika saya menambahkan OwnProps ke dalam campuran. Menggunakan <Bar /> di mana saja harus menimbulkan kesalahan karena alat peraga yang hilang a dan b , tetapi tidak, dan itu benar-benar mengganggu saya (tidak ada permainan kata-kata).

Saya menyiasatinya menggunakan ini

const ConnectedBar: React.ComponentType<OwnProps> = connect(mapStateToProps, mapDispatchToProps)(Bar);
export default ConnectedBar;

atau setara

export default connect(mapStateToProps, mapDispatchToProps)(Foo) as React.ComponentType<OwnProps>;

Saya telah memperbaiki masalah saya menggunakan React.FC<Props> untuk mengetik komponen fungsi dengan benar
Memperbarui posting asli

Ada pembaruan tentang ini? Seperti yang dikatakan @alexandrudanpop , menambahkan semua tipe itu alih-alih memiliki beberapa inferensi tipe dasar sepertinya bukan solusi yang baik. Saya menggunakan 7.2.1 dan saya masih memiliki masalah yang sama.

Di komponen saya yang lain, saya punya:

const connector = connect(mapStateToProps, mapDispatchToProps);
type PropsFromRedux = ConnectedProps<typeof connector>;
type Props = PropsFromRedux & OwnProps;

tetapi ini sepertinya tidak berhasil jika orang tua juga mengirim beberapa alat peraga.

Juga mengalami masalah yang sama.
Mulai rusak setelah pembaruan npm.
Perbaikan saya adalah sebagai berikut:
export default connect(mapStateToProps)(ConnectedIntlProvider) as unknown as ComponentType<unknown>;
Seperti tidak diketahui karena tidak ada OwnProps. Seharusnya hanya OwnProps yang pergi.

Namun, cara ini berfungsi:
export default connect<StateFromProps, null, OwnProps, ApplicationState>(mapStateToProps)(viewWithIntl);

Tapi cara ini tidak:
export default connect<StateFromProps, DispatchFromProps, OwnProps, ApplicationState>( mapStateToProps, mapDispatchToProps, )(attachmentFormWithIntel)
Dan itu membutuhkan akhiran:
as unknown as ComponentType<OwnProps>;

Menggunakan
"@types/react": "16.9.49",
"@types/react-redux": "^7.1.9",
"ketik": "^4.0.3"
"redux": "^4.0.5",
{
"ketergantungan": {
"bereaksi": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"redux": "^4.0.5",
},
"devDependencies": {
"@types/react": "16.9.49"
"@types/react-dom": "16.9.8",
"@types/react-redux": "^7.1.9",
"ketik": "^4.0.3"
}
}

Apakah halaman ini membantu?
0 / 5 - 0 peringkat