我很难用lodash方法为通过选择器连接到redux存储的React组件编写正确的类型。
在this article's conventions之后,组件的简化版本如下所示:
reducers / index.ts
interface ApiState {
api: {
entities: {
subscriptions: {
[pk: number]: {
imageUrl: string;
pk: number;
slug: string;
title: string;
};
};
};
result: {
subscriptions: never[];
};
};
…
};
export type RootState =
| (ApiState &
FirebaseState & {
router: Reducer<RouterState, LocationChangeAction>;
})
| {};
src / components / MyComponent.tsx
import React, {PureComponent} from "react";
import {connect} from "react-redux";
import {RootState} from "~/reducers";
interface OwnProps {
label: "host" | "experience";
score: number;
subscriptionPk: number;
}
interface StateProps {
subscription?: {
pk: number;
title: string;
};
}
const selectSubscriptions = state => state.api.entities.subscriptions;
const mapStateToProps = (state: RootState, ownProps: OwnProps): StateProps => ({
subscription: _.find(selectSubscriptions(state), {
pk: ownProps.subscriptionPk,
}) as any,
});
type Props = StateProps & OwnProps;
export default connect<StateProps, {}, OwnProps>(mapStateToProps)(
class extends PureComponent<Props> {
render() {
const {label, score, subscription} = this.props;
return (
<div>
{label} {score} {subscription.title}
</div>
);
}
},
);
src / typings.d.ts
// lodash global typing - begin
declare namespace _ {} // eslint-disable-line no-unused-vars
// lodash global typing - end
上面的代码在lodash find方法强制转换为mapStateToProp中的subscription: _.find() as any,
之前起作用。
如果我删除as any
,则会出现以下错误:
$ tsc --project tsconfig.json
src/components/MyComponent.tsx:37:3 - error TS2322: Type '{ pk: { toString: ...; toFixed: ...; toExponential: ...; toPrecision: ...; valueOf: ...; toLocaleString: ...; [Symbol.iterator]: ...; }; } | undefined' is not assignable to type '{ pk: number; slug: string; title: string; } | undefined'.
Type '{ pk: { toString: ...; toFixed: ...; toExponential: ...; toPrecision: ...; valueOf: ...; toLocaleString: ...; [Symbol.iterator]: ...; }; }' is missing the following properties from type '{ pk: number; slug: string; title: string; }': slug, title
37 subscription: _.find(selectSubscriptions(state), {
~~~~~~~~~~~~
src/components/MyComponent.tsx:26:3
26 subscription?: {
~~~~~~~~~~~~
The expected type comes from property 'subscription' which is declared here on type 'StateProps'
Found 1 error.
为什么lodash不能正确找出类型?我宁愿不必将所有lodash调用都强制转换为任何类型...
使用的版本:
答案 0 :(得分:1)
请不要提供泛型类型来进行不必要的连接。
在这里
import _ from "lodash";
import { PureComponent } from "react";
import React from "react";
import { connect } from "react-redux";
interface IApiState {
api: {
entities: {
subscriptions: {
[pk: number]: {
imageUrl: string;
pk: number;
slug: string;
title: string;
};
};
};
result: {
subscriptions: never[];
};
};
}
export type RootState = IApiState;
interface IOwnProps {
label: "host" | "experience";
score: number;
subscriptionPk: number;
}
interface ISubscription {
pk: number;
title: string;
}
interface IStateProps {
subscription?: ISubscription;
}
const selectSubscriptions = (state: RootState) =>
state.api.entities.subscriptions;
const mapStateToProps = (
state: RootState,
ownProps: IOwnProps,
) => ({
subscription: _.find(selectSubscriptions(state), {
pk: ownProps.subscriptionPk,
}),
});
type Props = IStateProps & IOwnProps;
export default connect(mapStateToProps)(
class extends PureComponent<Props> {
public render() {
const { label, score, subscription } = this.props;
return (
<div>
{label} {score} {subscription && subscription.title}
</div>
);
}
},
);