我有一些香草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"
}

当前回答

此外,你还可以这样做:

(this.DNATranscriber as any)[character];

编辑。

强烈建议使用正确的类型而不是任意类型强制转换对象。将对象强制转换为any只能帮助你在编译typescript时避免类型错误,但它不能帮助你保持代码的类型安全。

E.g.

interface DNA {
    G: "C",
    C: "G",
    T: "A",
    A: "U"
}

然后像这样转换:

(this.DNATranscriber as DNA)[character];

其他回答

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

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

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

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

您可以通过验证输入来修复错误,这是您无论如何都应该做的事情。

通过类型保护验证,下面的类型检查是正确的

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};

export default class Transcriptor {
    toRna(dna: string) {
        const codons = [...dna];
        if (!isValidSequence(codons)) {
            throw Error('invalid sequence');
        }
        const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
        return transcribedRNA;
    }
}

function isValidSequence(values: string[]): values is Array<keyof typeof DNATranscriber> {
    return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

值得一提的是,您似乎误解了将JavaScript转换为TypeScript需要使用类。

在下面的更习惯的版本中,我们利用TypeScript来提高清晰度,并在不改变实现的情况下获得更强的碱基对映射类型。我们使用一个函数,就像原来一样,因为它有意义。这很重要!将JavaScript转换为TypeScript与类无关,它与静态类型有关。

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};

export default function toRna(dna: string) {
    const codons = [...dna];
    if (!isValidSequence(codons)) {
        throw Error('invalid sequence');
    }
    const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function isValidSequence(values: string[]): values is Array<keyof typeof DNATranscriber> {
    return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

更新:

从TypeScript 3.7开始,我们可以更有表现力地编写它,使用断言签名形式化输入验证及其类型暗示之间的对应关系。

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
} as const;

type DNACodon = keyof typeof DNATranscriber;
type RNACodon = typeof DNATranscriber[DNACodon];

export default function toRna(dna: string): RNACodon[] {
    const codons = [...dna];
    validateSequence(codons);
    const transcribedRNA = codons.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function validateSequence(values: string[]): asserts values is DNACodon[] {
    if (!values.every(isValidCodon)) {
        throw Error('invalid sequence');    
    }
}
function isValidCodon(value: string): value is DNACodon {
    return value in DNATranscriber;
}

你可以在TypeScript 3.7发布说明中阅读更多关于断言签名的信息。

这里有一个不使用对象键的解决方案:

function toRna(value: string): string {
  return value.split('').map(ch => 'CGAU'['GCTA'.indexOf(ch)]).join('');
}

console.log(toRna('ACGTGGTCTTAA')); 
\\UGCACCAGAAUU

您可以使用返回类型来获取,就像这样。

getAllProperties(SellRent: number) : Observable<IProperty[]>{
return this.http.get<IProperty[]>('data/properties.json').pipe(
  map(data => {

    const propertiesArray: Array<IProperty> = [];
    for(const id in data){
      if(data.hasOwnProperty(id) && data[id].SellRent === SellRent){
        propertiesArray.push(data[id]);
      }
    }
    return propertiesArray;
  })
)

}

下面是数组对象的泛型类型的函数示例

const trimArrayObject = <T>(items: T[]) => {

  items.forEach(function (o) {

    for (let [key, value] of Object.entries(o)) {

      const keyName = <keyof typeof o>key;

      if (Array.isArray(value)) {

        trimArrayObject(value);

      } else if (typeof o[keyName] === "string") {

        o[keyName] = value.trim();

      }

    }

  });

};