Машинописный текст: не найдено сигнатуры индекса с параметром типа 'строка' для типа '{"A": строка; }

У меня есть некоторый ванильный код 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

Это работает как ожидалось. Теперь я хотел бы преобразовать это в машинопись.

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": string; }". Для типа> '{"A": строка не найдена подпись индекса с параметром типа' строка ': строка; }". ц (7053)

Я думал, что проблема в том, что мне нужен мой объектный ключ, чтобы быть строкой. Но преобразование их в строки не сработало.

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

Я очень смущен этим. Это говорит о том, что на моем объекте нет подписи индекса с типом строки. Но я уверен, что это так. Что я делаю неправильно?

Редактировать - я решил эту проблему, задав объекту DNATranscriber любой тип.

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

Ответ 1

Вы можете исправить ошибки, проверив введенные данные, что вы должны делать независимо от курса.

Следующие типы проверяются корректно с помощью проверок защиты типов

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};
export default class Transcriptor {
    toRna(sequence: string) {
        const sequenceArray = [...sequence];
        if (!isValidSequence(sequenceArray)) {
            throw Error('invalid sequence');
        }
        const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
        return transcribedRNA;
    }
}

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

Вот более идиоматическая версия

enum DNATranscriber {
    G = 'C',
    C = 'G',
    T = 'A',
    A = 'U'
}
export default function toRna(sequence: string) {
    const sequenceArray = [...sequence];
    if (!isValidSequence(sequenceArray)) {
        throw Error('invalid sequence');
    }
    const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

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

Обратите внимание на то, как мы используем перечисление строк TypeScript, чтобы улучшить ясность и усилить типизацию отображений базовой пары. Что еще более важно, обратите внимание, как мы используем function. Это важно! Преобразование JavaScript в TypeScript не имеет ничего общего с классами, оно связано со статическими типами.

Обновление:

Начиная с TypeScript 3.7, мы можем написать это более выразительно, формализуя соответствие между проверкой входных данных и их импликацией типов, используя сигнатуры утверждений.

enum DNATranscriber {
    G = 'C',
    C = 'G',
    T = 'A',
    A = 'U'
}
export default function toRna(sequence: string) {
    const sequenceArray = [...sequence];
    validateSequence(sequenceArray);
    const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function validateSequence(codons: string[]): asserts codons is Array<keyof typeof DNATranscriber> {
    if (!codons.every(isValidCodon)) {
        throw Error('invalid sequence');    
    }
}
function isValidCodon(codon: string): codon is keyof typeof DNATranscriber {
    return codon in DNATranscriber;
}

Подробнее о сигнатурах утверждений можно прочитать в объявлении TypeScript 3.7.

Ответ 2

Также вы можете сделать это:

(this.DNATranscriber as any)[character];