我遇到了Typescript的一个小问题。我正在尝试编写一些函数来简化对Redux状态的处理。
我具有用于创建某些实体状态的此接口:
export interface NormalizedState<T> {
byId: { [id: string]: T };
allIds: string[];
}
我有一些这样的MailState:
export interface MailState extends NormalizedState<Mail> {
inbox: string[]
}
我有一个函数可以像这样添加到byId属性:
type StringPropertyNames<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T];
const appendToState = <T, K extends StringPropertyNames<T>>(s: NormalizedState<T>) => (v: T[], p: K) =>
v.reduce((acc, m) => ({ ...acc, [m[p]]: m }), s.byId);
问题是我在appendToState函数中遇到错误
[m[p]]
我收到以下错误:
计算出的属性名称必须为“字符串”类型, “数字”,“符号”或“任何”。
所以我输入的内容似乎已关闭。任何帮助将不胜感激!
答案 0 :(得分:1)
您的类型很好,对于呼叫者来说应该可以。问题在于,在函数Typescript中,条件类型实际上不能做很多事情。因此,它不会试图找出T[K]
会变成string
的情况,它只会看到条件并放弃。
简单的解决方案是使用类型断言。
const appendToState = <T, K extends StringPropertyNames<T>>(s: NormalizedState<T>) => (v: T[], p: K) =>
v.reduce((acc, m) => ({ ...acc, [m[p] as string]: m }), s.byId);
另一种解决方案是颠倒您表达条件的方式。可以说K
必须具有类型T
的属性string
而不是T
是类型K
的{{1}}的任何键。对于编译器来说,这种替代方法更容易
string