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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:59:47  来源:igfitidea点击:

TypeScript: Object.keys return string[]

typescript

提问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 Optionsto activate strict: true.

带有strict: true. 游乐场:在这里,请选中所有复选框Options以激活strict: true

回答by Titian Cernicova-Dragomir

Object.keysreturns 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 keysin Objectthat will return the type you want:

您还可以为keysin创建一个别名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..inover 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

You can use the Extractutility type to conform your param to only those keyof typeof obj which are strings (which they are anyways).

您可以使用Extract实用程序类型使您的参数仅符合那些作为字符串的 keyof typeof obj (无论如何它们都是)。


    Object.keys(obj).forEach((key: Extract<keyof typeof obj, string>) => {
      const item = obj[key]
    })

回答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.keyslitterally we would get that typeof xis "a"|"b"[], but the actual value of xis ["a", "b", "c"]

如果我们Object.keys随便打字,我们会得到那个typeof xis "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 objdoesn't have properties beyond SimpleObjectuse 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[]