在类型上找不到带有“字符串”类型参数的索引签名

在类型上找不到带有“string”类型参数的索引签名

No index signature with a parameter of type ‘string’ was found on type

当我们使用类型的值来string索引具有特定键的对象时,会出现“No index signature with a parameter of type ‘string’ was found on type”的错误。

要解决该错误,请string使用 键入 作为对象的键之一
keyof typeof obj

没有找到带参数的索引签名

下面是错误如何发生的示例。

索引.ts
const key = 'country' as string; const obj = { name: 'Bobby Hadz', country: 'Germany', }; // ⛔️ Error: No index signature with a parameter of type // 'string' was found on type '{ name: string; country: string; }'.ts(7053) console.log(obj[key]);

key变量的类型为string,这可以是任何类型string

name当我们尝试访问具有和属性的对象时,我们收到了错误country

TypeScript 告诉我们string类型太宽泛,并非所有字符串都是对象中的键。我们必须确保特定字符串是对象的键之一。

使用类型断言解决错误

解决该错误的第一种方法是使用
类型断言

索引.ts
const key = 'country' as string; const obj = { name: 'Bobby Hadz', country: 'Germany', }; // 👇️ "Germany" console.log(obj[key as keyof typeof obj]); // 👇️ type OnlyKeys = 'name' | 'country' type OnlyKeys = keyof typeof obj;

我们使用类型断言向 TypeScript 指示该key变量不是类型string,而是仅
包含对象键的
联合类型。

现在,TypeScript 允许我们访问该属性而不会引发错误。

我们使用keyof typeof来获取对象键的联合类型。

如果您直接使用类型,则只需用于keyof MyType获取对象键的并集。

索引.ts
interface Employee { name: string; country: string; } const obj: Employee = { name: 'Bobby Hadz', country: 'Germany', }; const key = 'country' as string; // 👇️ "Germany" console.log(obj[key as keyof Employee]); // 👇️ type OnlyKeys = 'name' | 'country' type OnlyKeys = keyof Employee;
请注意,我们使用了keyof Employeeand not ,因为它是类型而不是对象。 keyof typeof EmployeeEmployee

key正确输入变量

解决此问题的更好方法是输入变量keyas ,
keyof Employee以向 TypeScript 指示string只会成为对象的键之一。

索引.ts
interface Employee { name: string; country: string; } const obj: Employee = { name: 'Bobby Hadz', country: 'Germany', }; // 👇️ key can only be one of the object's keys const key: keyof Employee = 'country'; // 👇️ "Germany" console.log(obj[key as keyof Employee]);

现在我们不必使用类型断言。

当我们有关于 TypeScript 不知道的值类型的信息时,使用类型断言。

使用它们时,我们有效地告诉 TypeScript 该值X将是类型Y,而不必担心它。如果我们错了,这可能会导致运行时错误。

这是另一个示例,说明如何键入仅作为对象键之一的值。

索引.ts
interface Employee { name: string; country: string; } const obj1: Employee = { name: 'Bobby Hadz', country: 'Germany', }; interface AccessEmployee { keyName: keyof Employee; // 👈️ one of Employee's keys } const obj2: AccessEmployee = { keyName: 'country', }; // 👇️ "Germany" console.log(obj1[obj2.keyName]);

我们使用该obj2.keyName属性来访问 中的属性obj1

为了能够做到这一点,我们必须将keyName属性键入obj2为 类型keyof Employee

keyName中的属性只能obj2具有值nameor
country,因此 TypeScript 允许我们安全地访问 中的特定属性
obj1

这是必要的,因为并非所有字符串都是特定对象中的键。为了让 TypeScript 让我们访问对象的属性,我们必须说服它该字符串是对象的键之一。

这是针对该错误最类型安全的解决方案,因为如果我们尝试将 的值更改obj2.keyName为不兼容的类型,就会收到错误。

索引.ts
interface Employee { name: string; country: string; } interface AccessEmployee { keyName: keyof Employee; // 👈️ one of Employee's keys } const obj2: AccessEmployee = { keyName: 'country', }; // ⛔️ Type '"something else"' is not assignable // to type 'keyof Employee'.ts(2322) obj2.keyName = 'something else';

尝试设置为或 以外obj2.keyName的任何其他值会导致类型检查器发出错误。namecountry

使用类型谓词来解决错误

如果您正在使用函数,您还可以使用类型谓词来确定字符串是否是该类型中的键之一。

索引.ts
type Employee = { id: number; name: string; salary: number; }; const employee: Employee = { id: 1, name: 'Bobby Hadz', salary: 100, }; function isAnEmployeeProperty(str: string): str is keyof Employee { return ['id', 'name', 'salary'].includes(str); } const myIdentifier = 'name' as string; if (isAnEmployeeProperty(myIdentifier)) { console.log(employee[myIdentifier]); // 👉️ "Bobby Hadz" }

语法str is keyof Employee
类型谓词

谓词采用函数签名中参数名称的parameter is Type形式 parameter

如果它与原始类型兼容,这允许 TypeScript 将变量缩小到特定类型。

isAnEmployeeProperty函数中,我们简单地检查传入的字符串是否是对象的键之一并返回结果。

如果我们进入if块,TypeScript 知道myIdentifier变量是对象中的键之一,并允许我们使用它来索引对象。

我还写了一篇关于
在 TS 中使用索引签名的详细指南。

额外资源

您可以通过查看以下教程来了解有关相关主题的更多信息: