【发布时间】:2022-02-12 17:14:34
【问题描述】:
这是我正在尝试做的一个简短示例:
import { connect } from "react-redux";
interface ErrorProps {
error: true;
description: string;
}
interface NoErrorProps {
error: false;
}
type TestProps = ErrorProps | NoErrorProps;
function Test(props: TestProps) {
return props.error ? <>Error: ${props.description}</> : <>OK</>;
}
// This is a test implementation that always returns no error
connect(() => ({ error: false }))(Test);
但是,我得到一个错误:
Argument of type '(props: TestProps) => Element' is not assignable to parameter of type 'ComponentType<Matching<{ error: boolean; } & DispatchProp<AnyAction>, TestProps>>'.
Type '(props: TestProps) => Element' is not assignable to type 'FunctionComponent<Matching<{ error: boolean; } & DispatchProp<AnyAction>, TestProps>>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'PropsWithChildren<Matching<{ error: boolean; } & DispatchProp<AnyAction>, TestProps>>' is not assignable to type 'TestProps'.
Type 'Matching<{ error: boolean; } & DispatchProp<AnyAction>, NoErrorProps> & { children?: ReactNode; }' is not assignable to type 'TestProps'.
Type 'Matching<{ error: boolean; } & DispatchProp<AnyAction>, NoErrorProps> & { children?: ReactNode; }' is not assignable to type 'NoErrorProps'.
Types of property 'error' are incompatible.
Type 'boolean' is not assignable to type 'false'.
现在,我已经使用代数数据类型 很长时间 了,并且通常对自己理解自己在做什么很有信心。但在这里,我会用(可能)非常明显的细节来解释我的推理,因为我很难过并怀疑我误解了一些非常基本和根本的东西。
我正在尝试解读此错误消息,虽然我不完全确定类型比较左侧发生了什么(使用 Redux 类型),但似乎每一行都是它前面的行的原因.所以,我看这两行,忽略左边的类型:
Type '...' is not assignable to type 'TestProps'. Type '...' is not assignable to type 'NoErrorProps'.
而且我注意到这意味着无论 '...' 意味着它不会改变,所以我在这里忽略它。但是这个序列不能分配给TestProps因为它不能分配给'NoErrorProps'。这意味着要分配给TestProps,它必须可以分配到NoErrorProps。
这没有任何意义。我刚刚检查过我仍然神志清醒:
const _1: TestProps = { error: false };
const _2: TestProps = { error: true, description: "foo" };
第一个变量不能分配给ErrorProps,第二个变量不能分配给NoErrorProps,但两者都可以完全分配给TestProps,因为这就是联合类型的工作方式。为什么上面错误信息中的行暗示相反?
【问题讨论】:
-
虽然这不是您问题的直接答案:我们强烈建议今天使用 React-Redux 挂钩 API 而不是
connect,这是主要原因之一这是因为 TS 类型大大更易于使用。请考虑改用挂钩。 -
这真是一件很奇怪又迂回的事情,所以我不知道我是否能雄辩地解释它。 TypeScript 中有时会出现无法将联合分配给自身的问题,因为联合类型
TestProps不能分配给联合的任何单个成员(ErrorProps或NoErrorProps)。这不是错误connect((): NoErrorProps => ({ error: false }))(Test);,而是connect((): TestProps => ({ error: false }))(Test); -
connectHOC 的类型非常复杂,并且依赖于大量的反向推理。例如,错误消息中显示的Matching类型是type Matching<InjectedProps, DecorationTargetProps> = { [P in keyof DecorationTargetProps]: P extends keyof InjectedProps ? InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : InjectedProps[P] : DecorationTargetProps[P]; }。而这只是其中的一部分! -
@markerikson 感谢您的推荐,我会记住这一点!但在这种情况下,我正在处理一个已经相当大的项目,并且在整个过程中对其进行重构是一个相当大的项目
标签: reactjs typescript redux algebraic-data-types union-types