当typescript被用来动态访问对象的属性(在方括号内)时,我正在尝试让typescript generic工作。
**最小示例:**
export type TaskType = 'withdraw' | 'pickup'
interface Task<T extends TaskType = TaskType> {
val: number
}
interface Memory {
tasks : {
[T in TaskType] : {
[targetId: string]: Task<T>
}
}
}
const data: Memory = {
tasks : {
withdraw : {
'a' : {val: 0}
},
pickup : {
'a' : {val: 0}
}
}
}
const res1 = data.tasks.withdraw.a; // Type is set correctly to Task<"withdraw">
let fn = function<T extends TaskType>(taskType: T) {
const res2 = data.tasks[taskType].a;
// ^ Type here is not being infered. It is Task<"withdraw"> | Task<"pickup">
};
正如您在上面的示例中看到的,当使用特定的键在函数外部调用时,res1
将返回正确的类型。
但当使用变量data.tasks[taskType].a;
时,它就不起作用了。res2
的类型应该是Task<T>
,而不是其他类型。我做错了什么?
更新:更多信息
我觉得我应该对我的实际问题进行更多的阐述。不同TaskTypes
之间的实际Task
接口不会重叠。我还有一个如下所示的函数。
interface Task<T extends TaskType = TaskType> {
val: number
resourceType: T extends 'withdraw' ? string : undefined
}
...
let claim = <T extends TaskType>(taskType: T, task: Task<T>) => {
data.tasks[taskType].a = task; // Why is task not assignable here ?
}
因为不同字符串之间的Task<T>
没有相同的属性,所以data.tasks[taskType].a = task;
行抛出一个错误。
我像这样调用索赔函数:
const pickupTask = {val: 0, resourceType: undefined} as Task<`pickup`>;
claim('pickup', pickupTask) // The function will always be called with the same tasktype i.e. calling claim('withdraw', pickupTask) should throw an error
从逻辑上讲,既然是taskType='pickup'
,那么参数pickupTask
应该能够被赋值给data.tasks[taskType].a
。那么为什么会抛出一个错误呢?我可能误解了typescript泛型,但我不确定我错在哪里。
另外,我不能将内存接口更改为通用接口。
发布于 2021-10-13 03:43:31
您需要对类型进行小的重构,并将data
作为参数之一。
export type TaskType = 'withdraw' | 'pickup'
interface Task<T extends TaskType = TaskType> {
val: number
}
type Memory<Type extends TaskType> = {
tasks: {
[T in Type]: {
[targetId: string]: Task<T>
}
}
}
const data: Memory<TaskType> = {
tasks: {
withdraw: {
'a': { val: 0 }
},
pickup: {
'a': { val: 0 }
}
}
}
const res1 = data.tasks.withdraw.a; // Type is set correctly to Task<"withdraw">
const fn = <
Key extends TaskType,
Data extends Memory<Key>
>(data: Data, taskType: Key) => {
const res2 = data.tasks[taskType].a; // Task<Key>
};
Memory
-应该使用feneric Type
https://stackoverflow.com/questions/69554116
复制