我有一些香草javascript代码,接受字符串输入,将字符串分割成字符,然后将这些字符匹配到对象上的键。

DNATranscriber = {
    "G":"C",
    "C": "G",
    "T": "A",
    "A": "U"
}
function toRna(sequence){
    const sequenceArray = [...sequence];
    const transcriptionArray = sequenceArray.map(character =>{
        return this.DNATranscriber[character];
    });

    return transcriptionArray.join("");
}

console.log(toRna("ACGTGGTCTTAA")); //Returns UGCACCAGAAUU

这与预期的一样。现在我想把它转换成typescript。

class Transcriptor {
    DNATranscriber = {
       G:"C",
       C: "G",
       T: "A",
       A: "U"
    }
    toRna(sequence: string) {
        const sequenceArray = [...sequence];
        const transcriptionArray = sequenceArray.map(character =>{
            return this.DNATranscriber[character];
        });
    }
}

export default Transcriptor

但是我得到了如下错误。

元素隐式具有“any”类型,因为类型“string”的表达式>不能用于索引类型“{"A":字符串;}”。 在类型>'{" a ":字符串上没有找到具有类型为'string'的参数的索引签名;}’.ts (7053)

我认为问题是我需要我的对象键是一个字符串。但是将它们转换为字符串并不管用。

DNATranscriber = {
       "G":"C",
       "C": "G",
       "T": "A",
       "A": "U"
    }

我对此很困惑。它表示在我的对象上不存在具有字符串类型的索引签名。但我确信它确实如此。我做错了什么?

编辑-我通过给DNATranscriber对象一个any类型来解决这个问题。

DNATranscriber: any = {
    "G":"C",
    "C":"G",
    "T":"A",
    "A":"U"
}

当前回答

例如,您可以使用Record。

let DNATranscriber: Record<string, string> = {};

其他回答

const Translator : { [key: string]: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U"
 }
 
 export function toRna(DNA:string) {

   const Translate = [...DNA];
   let Values = Translate.map((dna) => Translator[dna])
   if (Validate(Values)) {return Values.join('')}
 }

export function Validate(Values:string[]) : Boolean{
 if (Values.join('') === "" || Values.join('').length !== Values.length) throw Error('Invalid input DNA.');
 return true
}

我在对象中使用{[x:string]:string}。

const myObj:{[x:string]:string} = {
  'a': 'b'
};

function myFn() {
  const getVal = myObj['a'];
};

这就是我解决相关问题的方法

interface Map {
  [key: string]: string | undefined
}

const HUMAN_MAP: Map = {
  draft: "Draft",
}

export const human = (str: string) => HUMAN_MAP[str] || str

不要使用任何,使用泛型

// bad
const _getKeyValue = (key: string) => (obj: object) => obj[key];
    
// better
const _getKeyValue_ = (key: string) => (obj: Record<string, any>) => obj[key];
    
// best
const getKeyValue = <T extends object, U extends keyof T>(key: U) => (obj: T) =>
      obj[key];

坏-错误的原因是对象类型默认为空对象。因此,不可能使用字符串类型来索引{}。

更好的是,错误消失的原因是因为现在我们告诉编译器obj参数将是字符串/值(string/any)对的集合。然而,我们正在使用任何类型,所以我们可以做得更好。

Best - T扩展空对象。U扩展了T的键,所以U在T上永远存在,所以它可以作为一个查找值。

下面是一个完整的例子:

我已经切换了泛型的顺序(U extends keyof T现在出现在T extends object之前),以突出泛型的顺序并不重要,你应该选择一个对你的函数最有意义的顺序。

const getKeyValue = <U extends keyof T, T extends object>(key: U) => (obj: T) =>
  obj[key];

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Smith",
  age: 20
};

const getUserName = getKeyValue<keyof User, User>("name")(user);

// => 'John Smith'

替代语法

const getKeyValue = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];

我相信这个对你更好。

有了它,你可以在输入参数时得到建议(在编辑器中尝试一下),还有一个强返回类型供以后使用。

同样,受到Aluan Haddad答案的启发,你得到了序列验证,但更有效,因为验证是在转录循环内部进行的。

type DNAletter = 'G' | 'C' | 'T' | 'A';
type RNAletter = 'C' | 'G' | 'A' | 'U';

const DNATranscriber: { [key in DNAletter]: RNAletter } = {
  G: 'C',
  C: 'G',
  T: 'A',
  A: 'U'
};

// Return `RNAletter[]`
function toRna(sequence: string | string[] | DNAletter[]) {
  return ([...sequence] as DNAletter[]).map(character => {
    const transcribed = DNATranscriber[character];
    if (transcribed === undefined)
      throw Error(`Invalid character "${character}" in sequence`);
    return transcribed;
  });
}

编辑:从TS3.4开始,你可以使用const