typescript - TypeScript 不推断特定类型
问题描述
在下面的代码中,TypeScript 给出了map
函数错误:
类型“字符串”上不存在属性“地图”| 细绳[]'。
但propertyValue
在那种情况下是string[]
,因为propertyName
是'chapters'
。为什么 TypeScript 不知道呢?
interface Book {
title: string;
chapters: string[];
}
const setBookProperty = <K extends keyof Book>(propertyName: K, propertyValue: Book[K]) => ({
payload: { propertyName, propertyValue },
});
const reducer = (action: ReturnType<typeof setBookProperty>) => {
switch (action.payload.propertyName) {
case 'chapters': {
const x = action.payload.propertyValue.map(s => s === 'Chapter 1');
}
}
};
解决方案
ReturnType<typeof setBookProperty>
作为 for 的类型被评估一次,action
并且它返回的类型不维护 and 之间的任何propertyName
配对propertyValue
。相反,它是每个值的所有可能值的联合,没有任何理解一个依赖于另一个。
如果您检查 的类型action
,您会看到它是:
{
payload: {
propertyName: "title" | "chapters";
propertyValue: string | string[];
};
}
看到这一点,您可以理解如何缩小一个不会缩小另一个。
为了知道一个基于另一个的值,您的操作类型需要是所有有效配对的联合。这确实需要更多的代码,但它会得到你想要的结果。
定义一个通用操作,为特定键提供配对
type ActionSpecific<K extends keyof Book> = {
payload: {
propertyName: K,
propertyValue: Book[K]
}
}
使用映射来获取所有键的联合。在这种情况下,这很简单,因为我们只有两个键。
type ActionMap = {
[K in keyof Book]: ActionSpecific<K>
}
type ActionUnion = ActionMap[keyof Book]
ActionUnion
解析为,ActionSpecific<"title"> | ActionSpecific<"chapters">
因此它保持配对。如果您改为键入ActionSpecific<keyof Book>
,您将得到与之前丢失配对的相同错误类型。
(可选)声明返回类型setBookProperty
为ActionSpecific<K>
const setBookProperty = <K extends keyof Book>(propertyName: K, propertyValue: Book[K]): ActionSpecific<K> => ({
payload: { propertyName, propertyValue },
});
ActionUnion
用作减速器函数的类型action
,并且将switch
能够区分联合成员。
const reducer = (action: ActionUnion) => {
switch (action.payload.propertyName) {
case 'chapters': {
const x = action.payload.propertyValue.map(s => s === 'Chapter 1');
}
}
};
推荐阅读
- scala - ScalaTest:仅用于选定测试的 setup/tearDown 方法
- python - Matplotlib 对条形图进行错误排序
- java - 需要在 WebDriver 中选中一个复选框
- python - 如何从 Repo 安装 jasmin SMS Gateway the systemd
- javascript - 如何在 Python 中使用 Selenium 来获取 JavaScript 元素?
- c++ - 无法通过测试(Kadane 算法)
- vue.js - 状态更改时更新 getter 值 Vuex 存储
- python - 为什么添加到 OrderedDict 并在函数内部排序的键不会在函数外部保持排序?
- bash - 在 bash 中使用“exit ${?}”是否正确?
- spring-boot - Spring Retry 不再调用 maxAttempts