我的代码
import * as R from 'ramda';
import { ILPAsset } from 'shared/types/models';
interface TextMatchFunction {
(part: string, typed: string): boolean;
}
const textMatch: TextMatchFunction = (part: string, typed: string) => typed.search(part) !== -1;
export const filterAssets = (txt: string, assets: ILPAsset[]): ILPAsset[] => {
const checkText = (k: string, c: keyof ILPAsset) => (textMatch(txt, c[k].toLowerCase()) ? c : null);
const curriedCheckText = R.curry(checkText);
// @ts-ignore
const bySymbol = R.map(curriedCheckText('symbol'), assets);
return R.reject(R.isNil, bySymbol);
};
IPAsset的界面
export interface ILPAsset {
symbol: string;
lastPayout: number;
historical: number;
}
问题在这行上:
const checkText = (k: string, c: keyof ILPAsset) => (textMatch(txt, c[k].toLowerCase()) ? c : null);
Typescript期望k为数字c[k]
,而实际上它是ILPAsset中对象的键,在我的情况下,它是字符串,symbol
。
如何在Typescript中处理?
更简单的方法是进行此操作,但是我对将来有关密钥检查的问题有了很好的回答:D
export const filterAssets = (typed: string, assets: ILPAsset[]): ILPAsset[] => {
const checkSymbol = (asset: ILPAsset) =>
asset.symbol.includes(typed.toUpperCase());
return R.filter(checkSymbol, assets);
};
答案 0 :(得分:1)
引起此问题的原因是您使用k
作为c
的密钥。既然您提到,您期望k
是keyof ILPAsset
,这意味着c
应该是ILPAsset
。所以签名应该是:
const checkText = (k: keyof ILPAsset, c: ILPAsset) => (textMatch(txt, c[k].toLowerCase()) ? c : null);
剩下的问题是,由于c[k]
同时包含string
和ILPAsset
键,因此索引访问number
将不再是string
类型。 / p>
为此,我们有两种解决方案。
我们可以检查c[k]
是否为string
,是否不返回null
:
const checkText = (k: keyof ILPAsset, c: ILPAsset) => {
const v = c[k];
return typeof v === 'string' ? (textMatch(txt, v.toLowerCase()) ? c : null): null;
}
我们还可以过滤键,因此k
只能是键,而string
type StringKeys<T> = { [P in keyof T] : T[P] extends string ? P: never}[keyof T]
const checkText = (k: StringKeys<ILPAsset>, c: ILPAsset) => (textMatch(txt, c[k].toLowerCase()) ? c : null);
注意:string
的唯一ILPAsset
键是symbol
,因此也许您应该完全评估对k
参数的需求。为什么不只访问c.symbol
?