TypeScript 3.x: 访问未知类型的属性
TypeScript 3.x: Access properties of type unknown
我从 TypeScript 文档中了解到,您无法访问未知类型的属性:
// No property accesses, element accesses, or function calls
function f11(x: unknown) {
x.foo; // Error
x[5]; // Error
x(); // Error
new x(); // Error
}
但我不明白为什么?如果我可以分配包括对象在内的每个值,为什么我不能访问这些属性?
我正在应对以下场景:我有一个类型为 any
的对象,我将其传递给 Object.entries
方法,然后调用 forEach
.
因为它是 any
类型,forEach 调用参数将是一个数组,第一个元素是字符串类型,第二个元素是未知类型。
在我的例子中,第二个元素是一个对象,但我无法在不转换其类型的情况下访问它的属性,这似乎是错误的做法。
这是一个抛出 TS 错误的例子(只是一个抽象,我知道在这种情况下将其声明为 any 没有意义):
const obj: any = {
val1: "someval",
val2: {
some: "some",
object: "object",
},
};
Object.entries(obj).forEach(el => {
if (el[1].some) {
console.log(el);
}
});
我猜这也可能只是 Object.entries
方法的错误输入,但我仍然想解释一下,为什么我无法访问未知类型的属性。
总而言之,我的问题是:
- 为什么我不能访问类型未知的属性,即使类型未知可以是一个对象?
- 我想上述问题是有原因的,但
Object.entries
return 不应该是一个带有元素编号的数组。 0 类型字符串和元素 nr。任何类型的 1 个?
Object.entries(...)
的定义(取自GitHub)是:
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
由于您将 obj
明确定义为 any
,因此调用 Object.entries
returns
[string, unknown][]
您可以在声明 obj
时简单地删除 : any
,TypeScript 将从定义中推断其类型。
在这种情况下,对 Object.entries
的调用将 return:
[string, string | { some: string; object string; }][]
回答您的问题:
Why can't I access properties of type unknown?
编译器试图通过在编译时进行检查来避免运行时错误。如果你真的知道自己在做什么,你总是可以将 unknown
转换为 any
。例如:
const value:any = el[1];
I guess there is a reason for the above question, but shouldn't the Object.entries return an array w/ element nr. 0 of type string and element nr. 1 of type any?
它实际上 returns [string, unknown][]
.
我认为,为了解决您的问题,重要的是提供有关 any
与 unknown
的一些背景信息。虽然您可以在 official TypeScript documentation 中找到详尽的比较列表,但我想我可以大胆地将文章缩短为几句话:any
基本上是一种放之四海而皆准的方法,因此 不是类型安全的。我所说的类型安全是指您可以访问不存在的 any
的运行时 属性。
unknown
不一样。 unknown
在这方面与 any
相反。它通过声明 "I won't pretend I fit everything because I don't" 表示 any
的类型安全版本。因此 unknown
需要额外转换为所需的类型才能工作(因为它本身不具备任何属性)。
现在,进入实际问题。为什么 Object.entries
使用 unknown
而不是 any
?因为说 "cast this unknown value to whatever you need before usage, I won't assume that I know anything about this type" 比 "I don't know what kind of type it is, but I'll assume that it has all possible properties of all possible types".
更安全
我有同样的问题
但我尝试用这种技术来解决它
// choice is a custom data type
export interface Choice {
id: string;
isSelected: boolean;
score: number;
status: string;
}
for (const [key, value] of Object.entries(this.tableForm.value)) {
if (value) {
let choiceItem = value as Choice;
let choiceIds = [String(choiceItem.id)];
}
}
我从 TypeScript 文档中了解到,您无法访问未知类型的属性:
// No property accesses, element accesses, or function calls
function f11(x: unknown) {
x.foo; // Error
x[5]; // Error
x(); // Error
new x(); // Error
}
但我不明白为什么?如果我可以分配包括对象在内的每个值,为什么我不能访问这些属性?
我正在应对以下场景:我有一个类型为 any
的对象,我将其传递给 Object.entries
方法,然后调用 forEach
.
因为它是 any
类型,forEach 调用参数将是一个数组,第一个元素是字符串类型,第二个元素是未知类型。
在我的例子中,第二个元素是一个对象,但我无法在不转换其类型的情况下访问它的属性,这似乎是错误的做法。
这是一个抛出 TS 错误的例子(只是一个抽象,我知道在这种情况下将其声明为 any 没有意义):
const obj: any = {
val1: "someval",
val2: {
some: "some",
object: "object",
},
};
Object.entries(obj).forEach(el => {
if (el[1].some) {
console.log(el);
}
});
我猜这也可能只是 Object.entries
方法的错误输入,但我仍然想解释一下,为什么我无法访问未知类型的属性。
总而言之,我的问题是:
- 为什么我不能访问类型未知的属性,即使类型未知可以是一个对象?
- 我想上述问题是有原因的,但
Object.entries
return 不应该是一个带有元素编号的数组。 0 类型字符串和元素 nr。任何类型的 1 个?
Object.entries(...)
的定义(取自GitHub)是:
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
由于您将 obj
明确定义为 any
,因此调用 Object.entries
returns
[string, unknown][]
您可以在声明 obj
时简单地删除 : any
,TypeScript 将从定义中推断其类型。
在这种情况下,对 Object.entries
的调用将 return:
[string, string | { some: string; object string; }][]
回答您的问题:
Why can't I access properties of type unknown?
编译器试图通过在编译时进行检查来避免运行时错误。如果你真的知道自己在做什么,你总是可以将 unknown
转换为 any
。例如:
const value:any = el[1];
I guess there is a reason for the above question, but shouldn't the Object.entries return an array w/ element nr. 0 of type string and element nr. 1 of type any?
它实际上 returns [string, unknown][]
.
我认为,为了解决您的问题,重要的是提供有关 any
与 unknown
的一些背景信息。虽然您可以在 official TypeScript documentation 中找到详尽的比较列表,但我想我可以大胆地将文章缩短为几句话:any
基本上是一种放之四海而皆准的方法,因此 不是类型安全的。我所说的类型安全是指您可以访问不存在的 any
的运行时 属性。
unknown
不一样。 unknown
在这方面与 any
相反。它通过声明 "I won't pretend I fit everything because I don't" 表示 any
的类型安全版本。因此 unknown
需要额外转换为所需的类型才能工作(因为它本身不具备任何属性)。
现在,进入实际问题。为什么 Object.entries
使用 unknown
而不是 any
?因为说 "cast this unknown value to whatever you need before usage, I won't assume that I know anything about this type" 比 "I don't know what kind of type it is, but I'll assume that it has all possible properties of all possible types".
我有同样的问题 但我尝试用这种技术来解决它
// choice is a custom data type
export interface Choice {
id: string;
isSelected: boolean;
score: number;
status: string;
}
for (const [key, value] of Object.entries(this.tableForm.value)) {
if (value) {
let choiceItem = value as Choice;
let choiceIds = [String(choiceItem.id)];
}
}