Javascript 打字稿:在类型“{“A”:字符串;}
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/56568423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typescript: No index signature with a parameter of type 'string' was found on type '{ "A": string; }
提问by onTheInternet
I have some vanilla javascript code that takes a string input, splits the string into characters, and then matches those characters to a key on an object.
我有一些普通的 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
This works as expected. I'd now 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.
但我收到以下错误。
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; }'.ts(7053)
元素隐式具有 'any' 类型,因为类型 'string' 的表达式 > 不能用于索引类型 '{ "A": string; }'。在 type >'{ "A": string; 上找不到带有类型为“string”的参数的索引签名 }'.ts(7053)
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"
}
I'm quite confused by this. 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?
我对此很困惑。它说我的对象上不存在具有字符串类型的索引签名。但我确信确实如此。我究竟做错了什么?
Edit - I solved this by giving the DNATranscriber object a type of any.
编辑 - 我通过给 DNATranscriber 对象一个 any 类型来解决这个问题。
DNATranscriber: any = {
"G":"C",
"C":"G",
"T":"A",
"A":"U"
}
采纳答案by Aluan Haddad
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
以下类型检查正确,通过类型保护验证
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(value: string): value is keyof typeof DNATranscriber {
return value in DNATranscriber;
}
Here is a more idiomatic version
这是一个更惯用的版本
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(values: string[]): codons is Array<keyof typeof DNATranscriber> {
return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
return value in DNATranscriber;
}
Notice how we leverage a TypeScript string enumeration to improve clarity and gain stronger typing of base pair mappings. More importantly, notice how we use a function. This is important! Converting JavaScript to TypeScript has nothing to do with classes, it has to do with static types.
请注意我们如何利用 TypeScript 字符串枚举来提高清晰度并获得更强的碱基对映射类型。更重要的是,请注意我们如何使用function. 这个很重要!将 JavaScript 转换为 TypeScript 与类无关,它与静态类型有关。
Update:
更新:
Since TypeScript 3.7, we can write this more expressively, formalizing the correspondence between input validation and its type implication using assertion signatures.
从 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(values: string[]): asserts codons is Array<keyof typeof DNATranscriber> {
if (!values.every(isValidCodon)) {
throw Error('invalid sequence');
}
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
return value in DNATranscriber;
}
You can read more about assertion signaturesin the TypeScript 3.7 release notes.
您可以在TypeScript 3.7 发行说明 中阅读有关断言签名的更多信息。
回答by Leonardo Emilio Dominguez
Also, you can do this:
此外,您可以这样做:
(this.DNATranscriber as any)[character];
Edit.
编辑。
It's HIGHLYrecommended that you cast the object with the proper type instead of any. Casting an object as anyonly help you to avoid type errors when compiling typescript but it doesn't help you to keep your code type-safe.
它HIGHLY建议您投的对象,具有正确的类型,而不是any。将对象转换为any只能帮助您在编译打字稿时避免类型错误,但不能帮助您保持代码类型安全。
E.g.
例如
interface DNA {
G:"C",
C: "G",
T: "A",
A: "U"
}
And then you cast it like this:
然后你像这样投射它:
(this.DNATranscriber as DNA)[character];
回答by Mattijs
I resolved a similar issue in my getClassfunction like this:
我在我的getClass函数中解决了类似的问题,如下所示:
import { ApiGateway } from './api-gateway.class';
import { AppSync } from './app-sync.class';
import { Cognito } from './cognito.class';
export type stackInstances = typeof ApiGateway | typeof AppSync | typeof Cognito
export const classes = {
ApiGateway,
AppSync,
Cognito
} as {
[key: string]: stackInstances
};
export function getClass(name: string) {
return classes[name];
}
Typing my classesconst with my union type made typescript happy and it makes sense to me.
classes用我的联合类型输入我的const 使打字稿很高兴,这对我来说很有意义。
回答by Alex Mckay
Don't Use Any, Use Generics
不要使用任何,使用泛型
// 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];
Bad - the reason for the error is the objecttype is just an empty object by default. Therefore it isn't possible to use a stringtype to index {}.
不好 - 错误的原因是object默认情况下类型只是一个空对象。因此不可能使用string类型来索引{}。
Better - the reason the error disappears is because now we are telling the compiler the objargument will be a collection of string/value (string/any) pairs. However, we are using the anytype, so we can do better.
更好 - 错误消失的原因是因为现在我们告诉编译器obj参数将是字符串/值 ( string/any) 对的集合。但是,我们正在使用该any类型,因此我们可以做得更好。
Best - Textends empty object. Uextends the keys of T. Therefore Uwill always exist on T, therefore it can be used as a look up value.
最佳 -T扩展空对象。U扩展T. 因此U将始终存在于T,因此它可以用作查找值。
Here is a full example:
这是一个完整的例子:
I have switched the order of the generics (U extends keyof Tnow comes before T extends object) to highlight that order of generics is not important and you should select an order that makes the most sense for your function.
我已经切换了泛型的顺序(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'
回答by Flávio Teixeira Sales
You have two options with simple and idiomatic Typescript:
您有两个简单且惯用的 Typescript 选项:
- Use index type
- 使用索引类型
DNATranscriber: { [char: string]: string } = {
G: "C",
C: "G",
T: "A",
A: "U",
};
This is the index signature the error message is talking about. Reference
这是错误消息所谈论的索引签名。参考
- Type each property:
- 键入每个属性:
DNATranscriber: { G: string; C: string; T: string; A: string } = {
G: "C",
C: "G",
T: "A",
A: "U",
};
回答by John Galt
I messed around with this for awhile. Here was my scenario:
我弄乱了一段时间。这是我的场景:
I have two types, metrics1 and metrics2, each with different properties:
我有两种类型,metric1 和 metrics2,每个类型都有不同的属性:
type metrics1 = {
a: number;
b: number;
c: number;
}
type metrics2 = {
d: number;
e: number;
f: number;
}
At a point in my code, I created an object that is the intersection of these two types because this object will hold all of their properties:
在我的代码中,我创建了一个对象,它是这两种类型的交集,因为这个对象将保存它们的所有属性:
const myMetrics: metrics1 & metrics2 = {
a: 10,
b: 20,
c: 30,
d: 40,
e: 50,
f: 60
};
Now, I need to dynamically reference the properties of that object. This is where we run into index signature errors. Part of the issue can be broken down based on compile-timechecking and runtimechecking. If I reference the object using a const, I will not see that error because TypeScript can check if the property exists during compile time:
现在,我需要动态引用该对象的属性。这是我们遇到索引签名错误的地方。部分问题可以根据编译时检查和运行时检查进行分解。如果我使用const引用对象,则不会看到该错误,因为 TypeScript 可以在编译时检查该属性是否存在:
const myKey = 'a';
console.log(myMetrics[myKey]); // No issues, TypeScript has validated it exists
If, however, I am using a dynamic variable (e.g. let), then TypeScript will not be able to check if the property exists during compile time, and will require additional help during runtime. That is where the following typeguard comes in:
但是,如果我使用的是动态变量(例如let),则 TypeScript 将无法在编译时检查该属性是否存在,并且在运行时需要额外的帮助。这就是以下类型保护的用武之地:
function isValidMetric(prop: string, obj: metrics1 & metrics2): prop is keyof (metrics1 & metrics2) {
return prop in obj;
}
This reads as,"If the objhas the property propthen let TypeScript know that propexists in the intersection of metrics1 & metrics2." Note: make sure you surround metrics1 & metrics2 in parentheses after keyofas shown above, or else you will end up with an intersection between the keys of metrics1 and the type of metrics2 (not its keys).
这读作,“如果obj具有属性prop,那么让 TypeScript 知道prop存在于 metrics1 和 metrics2 的交集中。” 注意:确保将 metrics1 和 metrics2 括在keyof后面的括号中,如上所示,否则最终会出现 metrics1 的键和 metrics2 的类型(而不是它的键)之间的交集。
Now, I can use the typeguard and safely access my object during runtime:
现在,我可以使用 typeguard 并在运行时安全地访问我的对象:
let myKey:string = '';
myKey = 'a';
if (isValidMetric(myKey, myMetrics)) {
console.log(myMetrics[myKey]);
}

