我有一个高阶组件为我处理Firestore数据。我对打字稿还很陌生,但在按我希望的方式工作时遇到了麻烦。
Here are the full files + some extra ts definitions
我有几个问题:
React.Component无法推断类型定义:
type WithFirestoreHoC<Props = {}> = (
config: WithFirestoreConfig<Props>,
) => (
WrappedComponent: ComponentType<WithFirestore & Props>,
) => ComponentClass<Props, { error: Error; queries: {}; loaded: boolean }>;
const withFirestore: WithFirestoreHoC = ({
queries,
props: propPickList,
loading: { delay = 200, timeout = 0 } = {},
}) => WrappedComponent =>
class WithFirestoreConnect extends Component { ... }
config
和WrappedComponent
正在获取其类型定义(分别为WithFirestoreConfig
+ ComponentType<WithFirestore & Props>
。
但是,WithFirestoreConnect
并不暗示它应该是ComponentClass<Props, { error: Error; queries: {}; loaded: boolean }>
。
我不介意两次定义状态,但这并不能帮助我将Props
从type WithFirestoreHoC<Props = {}>
转移到class WithFirestoreConnect extends Component<Props, { error: Error; queries: {}; loaded: boolean }> { ... }
,因为它找不到Props
如何创建动态选择列表
WithFirestoreConfig
的一部分定义了配置对象具有传递到WrappedComponent
的道具列表
WrappedComponent: ComponentType<WithFirestore & Props>,
应该真的是
WrappedComponent: ComponentType<WithFirestore & Pick<Props, config.propsPickList>,
有没有一种方法可以告诉打字稿您在config.propsPickList
中提供的内容将决定WrappedComponent
应该拥有哪些道具?
推断Firestore类型
Firestore查询响应有两种类型,分别是“文档”和“集合/查询”。如果可以在config.queries
中将它们定义为这样的话,那将是惊人的:
{ queries: {
docQuery: myDocument as DocumentReference<docDataType>,
collectionQuery: myDocument as CollectionReference<docDataType>,
} }
因此WrappedComponent可以知道在另一端是否需要查询或文档数据结构。
这似乎超级复杂,因此我在这里有一个简单的示例(这是创建单个订阅的快捷方式),至少可以成为实现所需目标的好垫脚石:
export const withFirestoreDocument: <
DataType = firestore.DocumentData,
Props = {}
>(
query: FirestoreQueryable<DataType>,
) => (
WrappedComponent: ComponentType<DocumentSnapshotExpanded<DataType>>,
) => WithFirestoreHoC<Props> = query => WrappedComponent =>
withFirestore({ queries: { _default: query } })(
mapProps<
DocumentSnapshotExpanded<DataType> & Props,
{ _default: DocumentSnapshotExpanded<DataType> } & Props
>(({ _default, ...props }) => ({ ...props, ..._default }))(WrappedComponent),
);
但是由于无法从函数的类型定义中提取mapProp
的类型定义,我被困在这里了……什么是正确的方法?
答案 0 :(得分:1)
React.Component无法推断类型定义:使import React from "react";
import PlayerAPI from "../api";
import { Link } from "react-router-dom";
export default ({ match: { params } }) => {
const player = PlayerAPI.get(parseInt(params.id, 10));
return !player ? (
<div style={{ padding: "0px 20px" }}>
Sorry, but the player was not found
</div>
) : (
<div style={{ padding: "0px 20px" }}>
<h1>
{player.name} (#{player.number})
</h1>
<h2>Position: {player.position}</h2>
<Link to="/roster">Back</Link>
</div>
);
};
成为函数的类型参数而不是类型别名,然后在定义Props
时声明它。
如何创建动态选择列表::为选择列表元素的并集添加withFirestore
类型的参数。当您让TypeScript在调用站点上推断PL
时,这将做正确的事情,尽管调用者有可能通过指定PL
为并集类型(包括不在实际位置中的元素)来产生不合理的行为。列表。
推断Firestore类型:我不确定您要使用PL
的去向。您可以使用另一个withFirestoreDocument
类型的参数以及一些映射类型和条件类型来执行此操作,以从Q
生成注入的道具的类型。
这是我对Q
的修订,其中包含所有新功能,一些无关的修补程序以使其可以在我的环境中进行编译,并在底部添加了一个示例(可能应该放在单独的文件中):
withFirestore.tsx