typescript 打字稿:Object.keys 返回字符串[]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/52856496/
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: Object.keys return string[]
提问by amaurymartiny
When using Object.keys(obj)
, the return value is a string[]
, whereas I want a (keyof obj)[]
.
使用时Object.keys(obj)
,返回值是 a string[]
,而我想要 a (keyof obj)[]
。
const v = {
a: 1,
b: 2
}
Object.keys(v).reduce((accumulator, current) => {
accumulator.push(v[current]);
return accumulator;
}, []);
I have the error:
我有错误:
Element implicitly has an 'any' type because type '{ a: number; b: number; }' has no index signature.
元素隐式具有 'any' 类型,因为类型 '{ a: number; b:数量;}' 没有索引签名。
TypeScript 3.1 with strict: true
. Playground: here, please check all checkboxes in Options
to activate strict: true
.
带有strict: true
. 游乐场:在这里,请选中所有复选框Options
以激活strict: true
。
回答by Titian Cernicova-Dragomir
Object.keys
returns a string[]
. This is by design as described in this issue
Object.keys
返回一个string[]
. 这是设计使然,如本期所述
This is intentional. Types in TS are open ended. So keysof will likely be less than all properties you would get at runtime.
这是故意的。TS 中的类型是开放式的。因此,keysof 可能会少于您在运行时获得的所有属性。
There are several solution, the simplest one is to just use a type assertion:
有几种解决方案,最简单的一种是使用类型断言:
const v = {
a: 1,
b: 2
};
var values = (Object.keys(v) as Array<keyof typeof v>).reduce((accumulator, current) => {
accumulator.push(v[current]);
return accumulator;
}, [] as (typeof v[keyof typeof v])[]);
You can also create an alias for keys
in Object
that will return the type you want:
您还可以为keys
in创建一个别名Object
,它将返回您想要的类型:
export const v = {
a: 1,
b: 2
};
declare global {
interface ObjectConstructor {
typedKeys<T>(o: T) : Array<keyof T>
}
}
Object.typedKeys = Object.keys as any
var values = Object.typedKeys(v).reduce((accumulator, current) => {
accumulator.push(v[current]);
return accumulator;
}, [] as (typeof v[keyof typeof v])[]);
回答by amaurymartiny
As a possible solution, you can iterate using for..in
over your object:
作为一种可能的解决方案,您可以迭代使用for..in
您的对象:
for (const key in myObject) {
console.log(myObject[key].abc); // works!
}
While this, as you said, would not work:
虽然这,正如你所说,是行不通的:
for (const key of Object.keys(myObject)) {
console.log(myObject[key].abc); // doesn't!
}
回答by Corban Brook
回答by Ben Carp
Based on Titian Cernicova-Dragomir answer and comment
基于 Titian Cernicova-Dragomir 的回答和评论
Why
为什么
One of TypeScript's core principles is that type checking focuses on the shape that values have. (reference)
TypeScript 的核心原则之一是类型检查侧重于值的形状。(参考)
Let's see what would happen if by default we would type Object.keys "literally":
让我们看看如果默认情况下我们“按字面意思”键入 Object.keys 会发生什么:
interface SimpleObject {
a: string
b: string
}
const getKeys = (obj:SimpleObject) => Object.keys(obj)
const obj = {
a: "article",
b: "bridge",
c: "Camel"
}
const x = getKeys(obj) // valid since obj has the shape of SimpleObject
If we type Object.keys
litterally we would get that typeof x
is "a"|"b"[]
, but the actual value of x
is ["a", "b", "c"]
如果我们Object.keys
随便打字,我们会得到那个typeof x
is "a"|"b"[]
,但实际的值x
是["a", "b", "c"]
Type assertion is exactly for such cases - when the programmer has additional knowledge. In this case, if you know that obj
doesn't have properties beyond SimpleObject
use type assertion.
类型断言正好适用于这种情况——当程序员有额外的知识时。在这种情况下,如果您知道obj
除了SimpleObject
使用类型断言之外没有其他属性。
Solution
解决方案
Instead of Object.keys(obj)
use (Object.keys(obj) as Array<keyof typeof obj>)
而不是Object.keys(obj)
使用(Object.keys(obj) as Array<keyof typeof obj>)
Deprecated Original answer
已弃用的原始答案
You can use the following general function wrapper
您可以使用以下通用函数包装器
const getObjectKeys = <O extends object>(obj:O) => Object.keys(obj) as Array<keyof O>
回答by Jeff Stock
See https://github.com/microsoft/TypeScript/issues/20503.
请参阅https://github.com/microsoft/TypeScript/issues/20503。
declare const BetterObject: {
keys<T extends {}>(object: T): (keyof T)[]
}
const icons: IconName[] = BetterObject.keys(IconMap)
Will retain type of keys instead of string[]
将保留键的类型而不是 string[]