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

Javascript 如何更改索引表达式的类型?ie:c[k],javascript,typescript,indexof,keyof,Javascript,Typescript,Indexof,Keyof,我的代码 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)

我的代码

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;
}
IPAsset的界面

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

在Typescript中如何处理这个问题

更新 顺便说一句,这是一个简单得多的方法,但是我得到了一个关于密钥检查的未来问题的很好的答案: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
是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
只能是键,而不是
字符串

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);
type StringKeys={[P in keyof T]:T[P]扩展字符串?P:never}[keyof T]
const checkText=(k:StringKeys,c:ILPAsset)=>(textMatch(txt,c[k].toLowerCase())?c:null);

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

如果
c
是一个
ILPAsset
为什么被声明为
string
?@TitianCernicova Dragomir你是对的,我已经颠倒了键,但错误仍然是一样的:(
(k:string,c:keyof ILPAsset)
如何
(k:keyof ILPAsset,c:ILPAsset)
是我所期望的,它应该基于您如何使用它。
k
被用作
c
的键。您说
k
需要是
ILPAsset
的键,所以如果
k
ILPAsset
的键,
k
被用作
c
的键,那么
c
应该是
ILPAsset
@TitianCernicova Dragomir啊,是的,它删除了
k
下的错误,但是我在
.toLowerCase()
上得到了一个错误,因为它仍然认为我正在尝试在
数字上这样做。我想你不需要其他问题,我很快会回答,我们会从那里开始:)哇,太性感了!甚至不知道一种类型的
从不
。。。我得慢慢读这类文字,看看到底是怎么回事,呵呵。你是对的,我应该使用
c.symbol
@LeonGaban条件类型magic:)