如何更改索引表达式的类型?即:c[k]



My Code

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);
};

国际音标的接口

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

在打字稿中如何处理?

更新

顺便说一句,这是一种更简单的方法,但是对于有关密钥检查的未来问题,我得到了很好的答案:D

export const filterAssets = (typed: string, assets: ILPAsset[]): ILPAsset[] => {
const checkSymbol = (asset: ILPAsset) => 
asset.symbol.includes(typed.toUpperCase());
return R.filter(checkSymbol, assets);
};

导致此问题是因为您使用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键。

我们对此有两种解决方案。

我们可以检查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);

注意ILPAsset的唯一string键是symbol,因此也许您应该评估是否需要k参数。为什么不直接访问c.symbol

最新更新