TypeScript 不安全地使用 'any' 类型的表达式错误
TypeScript Unsafe use of expression of type 'any' ERROR
我是 TypeScript 的新手,描述我的场景如下:
我有这样的类型:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
每个单独的水果数量都有验证,在本例中是 appleQuantity、bananaQuantity 和 pearQuantity,这意味着我需要从响应中获取每个单独的水果数量。
所以我创建了一个字符串数组来保存单个 属性 键,如下所示:
const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]
函数逻辑如下:
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter];
...
}
但是当我构建时,TSLint 在 response[individualParameter]
处抛出错误说
Unsafe use of expression of type 'any'
我认为这是因为响应无法从字符串数组元素中识别类型?
我是 TypeScript 的新手,很好奇解决这个问题的好方法。
问题出在这一行:const individualParameters:string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]
。
根据 individualParameters
的类型定义,每个元素都是一个 string
。这意味着即使这个 "foo"
字符串也可以分配给类型 string
.
因此,typescript 拒绝使用 response[individualParameter]
,因为 response
是一种具有严格键的类型,而 individualParameter
可能是任何字符串。
为了让它工作,你可以使用const assertion
:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
const individualParameters = ["appleQuantity", "bananaQuantity", "pearQuantity"] as const
declare const response: response;
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter]; // ok
}
如果你不喜欢as const
方法,你可以使用额外的功能:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
declare const response: response;
const iterator = <
Obj extends Record<string, number>,
Keys extends Array<keyof Obj>
>(record: Obj, keys: Keys) => {
for (const individualParameter of keys) {
let individualQuantity = record[individualParameter];
}
}
iterator(response, ['foo']) // expected error
// works only with literal array
iterator(response, ["appleQuantity", "bananaQuantity", "pearQuantity"]) // ok
Obj
- 表示 response
参数,
Keys
- 确保第二个数组参数包含有效的 Obj
keys
P.S。根据 TS 约定,类型应该大写。
您需要使您的回复可索引。有关更多信息,请参见 here.
在您的情况下,可以使用如下接口来完成:
interface IResponse {
[key: string]: number; // <- This line makes your interface indexable
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
}
现在您只需确保您的响应实现了 IResponse 接口:
const response: IResponse = {
totalQuantity: 1,
numberOfCatogory: 2,
appleQuantity: 3,
bananaQuantity: 4,
pearQuantity: 5
}
在此之后,您可以使用字符串数组获取单个水果数量,如下所示:
const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];
for (let individualParameter of individualParameters) {
console.log(response[individualParameter]);
}
// Output:
// 3
// 4
// 5
一个简单的方法是您可以选择将类型的键作为字符串变量
type response = {
[key: string]: number;
};
但如果你真的要修复键为 appleQuantity、bananaQuantity、blablabla
您可以尝试 Mapped Type,单击此 link 了解更多详情
https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
所以我认为大多数人已经解释了发生了什么,我认为到目前为止我个人最喜欢的答案是 。他把问题解释的很好:
Hence, typescript rejects using response[individualParameter] because response is a type with strict keys whereas individualParameter might be any string.
但是,这个问题可以通过告诉 Typescript 您正在定义一个包含字符串的数组来轻松解决,这些字符串也是您尝试访问的类型的键:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
// this should be your non-null and defined object in reality
let response: response;
// just this one line below was altered
const individualParameters: (keyof response)[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter];
}
(keyof response)[]
类型意味着您将始终拥有一个仅包含 response
类型键的数组。在我的示例中,此声明是多余的,因为编译器已经可以推断出您定义的所有属性都是该类型的键,但是当 for 循环在函数中时,情况就不同了,例如。我假设你是这种情况,否则你不会在第一种情况下问这个问题。
@captain-yossarian 是对的;根据 TS 约定,类型 应该 大写。
我是 TypeScript 的新手,描述我的场景如下:
我有这样的类型:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
每个单独的水果数量都有验证,在本例中是 appleQuantity、bananaQuantity 和 pearQuantity,这意味着我需要从响应中获取每个单独的水果数量。
所以我创建了一个字符串数组来保存单个 属性 键,如下所示:
const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]
函数逻辑如下:
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter];
...
}
但是当我构建时,TSLint 在 response[individualParameter]
处抛出错误说
Unsafe use of expression of type 'any'
我认为这是因为响应无法从字符串数组元素中识别类型?
我是 TypeScript 的新手,很好奇解决这个问题的好方法。
问题出在这一行:const individualParameters:string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"]
。
根据 individualParameters
的类型定义,每个元素都是一个 string
。这意味着即使这个 "foo"
字符串也可以分配给类型 string
.
因此,typescript 拒绝使用 response[individualParameter]
,因为 response
是一种具有严格键的类型,而 individualParameter
可能是任何字符串。
为了让它工作,你可以使用const assertion
:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
const individualParameters = ["appleQuantity", "bananaQuantity", "pearQuantity"] as const
declare const response: response;
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter]; // ok
}
如果你不喜欢as const
方法,你可以使用额外的功能:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
declare const response: response;
const iterator = <
Obj extends Record<string, number>,
Keys extends Array<keyof Obj>
>(record: Obj, keys: Keys) => {
for (const individualParameter of keys) {
let individualQuantity = record[individualParameter];
}
}
iterator(response, ['foo']) // expected error
// works only with literal array
iterator(response, ["appleQuantity", "bananaQuantity", "pearQuantity"]) // ok
Obj
- 表示 response
参数,
Keys
- 确保第二个数组参数包含有效的 Obj
keys
P.S。根据 TS 约定,类型应该大写。
您需要使您的回复可索引。有关更多信息,请参见 here.
在您的情况下,可以使用如下接口来完成:
interface IResponse {
[key: string]: number; // <- This line makes your interface indexable
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
}
现在您只需确保您的响应实现了 IResponse 接口:
const response: IResponse = {
totalQuantity: 1,
numberOfCatogory: 2,
appleQuantity: 3,
bananaQuantity: 4,
pearQuantity: 5
}
在此之后,您可以使用字符串数组获取单个水果数量,如下所示:
const individualParameters: string[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];
for (let individualParameter of individualParameters) {
console.log(response[individualParameter]);
}
// Output:
// 3
// 4
// 5
一个简单的方法是您可以选择将类型的键作为字符串变量
type response = {
[key: string]: number;
};
但如果你真的要修复键为 appleQuantity、bananaQuantity、blablabla 您可以尝试 Mapped Type,单击此 link 了解更多详情 https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
所以我认为大多数人已经解释了发生了什么,我认为到目前为止我个人最喜欢的答案是
Hence, typescript rejects using response[individualParameter] because response is a type with strict keys whereas individualParameter might be any string.
但是,这个问题可以通过告诉 Typescript 您正在定义一个包含字符串的数组来轻松解决,这些字符串也是您尝试访问的类型的键:
type response = {
totalQuantity: number;
numberOfCatogory: number
appleQuantity: number;
bananaQuantity: number;
pearQuantity: number;
};
// this should be your non-null and defined object in reality
let response: response;
// just this one line below was altered
const individualParameters: (keyof response)[] = ["appleQuantity", "bananaQuantity", "pearQuantity"];
for (const individualParameter of individualParameters) {
let individualQuantity = response[individualParameter];
}
(keyof response)[]
类型意味着您将始终拥有一个仅包含 response
类型键的数组。在我的示例中,此声明是多余的,因为编译器已经可以推断出您定义的所有属性都是该类型的键,但是当 for 循环在函数中时,情况就不同了,例如。我假设你是这种情况,否则你不会在第一种情况下问这个问题。
@captain-yossarian 是对的;根据 TS 约定,类型 应该 大写。