输入 lodash 函数的正确方法是啥?
Posted
技术标签:
【中文标题】输入 lodash 函数的正确方法是啥?【英文标题】:What is the proper way to type lodash functions?输入 lodash 函数的正确方法是什么? 【发布时间】:2019-05-07 22:08:07 【问题描述】:我很难为使用 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 方法被转换为 any 之前工作:subscription: _.find() as any,
in mapStateToProp。
如果我删除 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 调用都转换为 any...
使用的版本:
反应 16.6.3 redux 4.0.1 react-redux 5.1.1 lodash-webpack-plugin 0.11.5(本身使用 lodash ^4.17.4) @types/lodash 4.14.119【问题讨论】:
【参考方案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>
);
,
);
【讨论】:
感谢您的回复!我尝试更改_.find() as any
→ _.find()
和connect<StateProps, , OwnProps>
→ connect
,但_find 行上的错误仍然存在。这似乎不是解决方案。此外,我发现 connect 泛型类型声明对于理解它通常期望的内容非常有用。
您的示例还提示了一个不相关的问题。老实说,我还不清楚类型和接口之间的区别,在我目前的使用情况下,它看起来几乎是一样的(接口更灵活一些)。因此,我想知道为什么有几个人使用这个 I 前缀命名约定来区分接口和类型。只是偏好/习惯的问题,还是背后有更严重的原因?
我在我的一个解决方案上尝试了这个,并且我使用了一个要求 I 在接口名称之前的 linter,这只是一个约定。但是,就像我说的那样,我试过了,它奏效了。那么如果有可能你可以创建一个 git repo 吗?以上是关于输入 lodash 函数的正确方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
为输入类型文件键入 onChange 处理程序的正确方法是啥?