patternjavascriptCritical
No index signature with a parameter of type 'string' was found on type '{ "A": string; }
Viewed 0 times
indexwithsignaturefoundparameterstringtypewas
Problem
I have vanilla JavaScript code that takes a string input, splits the string into characters, then matches those characters to a key on an object:
I'd like to convert this to TypeScript:
But I'm getting the following error:
TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "A": string; }'.
No index signature with a parameter of type 'string' was found on type >'{ "A": string; }'.
I thought that the issue was that I needed my object key to be a string. But converting them to strings didn't work:
It says that no index signature with a type of string exists on my object, but I'm sure that it does. What am I doing wrong? Note: The error message is not raised if I explicitly annotate the variable as having the
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
I'd like to convert this to 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
But I'm getting the following error:
TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "A": string; }'.
No index signature with a parameter of type 'string' was found on type >'{ "A": string; }'.
I thought that the issue was that I needed my object key to be a string. But converting them to strings didn't work:
DNATranscriber = {
"G": "C",
"C": "G",
"T": "A",
"A": "U"
}
It says that no index signature with a type of string exists on my object, but I'm sure that it does. What am I doing wrong? Note: The error message is not raised if I explicitly annotate the variable as having the
any type.Solution
You can fix the errors by validating your input, which is something you should do regardless of course.
The following typechecks correctly, via type guarding validations
Playground Link
It is worth mentioning that you seem to be under the misapprehention that converting JavaScript to TypeScript involves using classes.
In the following, more idiomatic version, we leverage TypeScript to improve clarity and gain stronger typing of base pair mappings without changing the implementation. We use a
Playground Link
Update:
Since TypeScript 3.7, we can write this more expressively, formalizing the correspondence between input validation and its type implication using assertion signatures.
Playground Link
You can read more about assertion signatures in the TypeScript 3.7 release notes.
The following typechecks correctly, via type guarding validations
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 {
return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
return value in DNATranscriber;
}Playground Link
It is worth mentioning that you seem to be under the misapprehention that converting JavaScript to TypeScript involves using classes.
In the following, more idiomatic version, we leverage TypeScript to improve clarity and gain stronger typing of base pair mappings without changing the implementation. We use a
function, just like the original, because it makes sense. This is important! Converting JavaScript to TypeScript has nothing to do with classes, it has to do with static types.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 {
return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
return value in DNATranscriber;
}Playground Link
Update:
Since TypeScript 3.7, we can write this more expressively, formalizing the correspondence between input validation and its type implication using assertion signatures.
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;
}Playground Link
You can read more about assertion signatures in the TypeScript 3.7 release notes.
Code Snippets
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;
}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;
}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;
}Context
Stack Overflow Q#56568423, score: 128
Revisions (0)
No revisions yet.