1. ホーム
  2. javascript

[解決済み] タイプスクリプトです。タイプ '{ "A": string; }' で 'string' 型のパラメータを持つインデックス署名が見つかりませんでした。

2022-04-25 16:14:44

質問

文字列を入力し、文字列を文字に分割し、それらの文字をオブジェクトのキーにマッチさせるバニラ・ジャバスクリプトのコードがあるのですが、どのようにすればよいでしょうか?

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

しかし、次のようなエラーが発生します。

string' 型の式は '{ "A": string; }' 型のインデックスに使用できないため、要素は暗黙的に 'any' 型を持ちます。 タイプ 'string' のパラメータを持つインデックス署名は、タイプ >'{ "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"
}

解決方法は?

入力の検証を行うことで、エラーを修正することができます。もちろん、これは関係なく行うべきことです。

以下のタイプチェックは、タイプガードによる検証で正しく行われます。

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を活用して、実装を変更することなく、ベースペアマッピングをより明確に、より強く型付けすることができるようになっています。ここでは function というのも、オリジナルと同じように、理にかなっているからです。これは重要なことです。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 リリースノート .