使用时Object.keys(obj),返回值为a string[],而我想要一个(keyof obj)[]。
const v = {
a: 1,
b: 2
}
Object.keys(v).reduce((accumulator, current) => {
accumulator.push(v[current]);
return accumulator;
}, []);
Run Code Online (Sandbox Code Playgroud)
我有错误:
元素隐式地具有“ any”类型,因为类型为“ {{a:number; b:数字;}'没有索引签名。
带有TypeScript 3.1 strict: true。游乐场:在这里,请选中所有复选框以Options将其激活strict: true。
Ben*_*arp 41
仅当您知道对象没有额外属性时才使用类型断言(对象字面量就是这种情况,而不是对象参数就是这种情况)。
显式断言
Object.keys(obj) as Array<keyof typeof obj>
Run Code Online (Sandbox Code Playgroud)
隐藏断言
const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>
Run Code Online (Sandbox Code Playgroud)
使用getKeys代替Object.keys。getKeys是对 的引用Object.keys,但返回是按字面输入的。
TypeScript 的核心原则之一是类型检查侧重于值的形状。(参考)
interface SimpleObject {
a: string
b: string
}
const x = {
a: "article",
b: "bridge",
c: "Camel"
}
Run Code Online (Sandbox Code Playgroud)
x有资格作为 aSimpleObject因为它有它的形状。这意味着当我们看到 a 时SimpleObject,我们知道它有属性a和b,但它也可能有其他属性。
const someFunction = (obj: SimpleObject) => {
Object.keys(obj).forEach((k)=>{
....
})
}
someFunction(x)
Run Code Online (Sandbox Code Playgroud)
让我们看看如果默认情况下我们按照 OP 的“字面意思”键入 Object.keys 会发生什么:
我们会得到那typeof k是"a"|"b"。迭代时,实际值将是a, b, c。Typescript 通过输入 k 作为字符串来保护我们免受此类错误的影响。
类型断言正好适用于这种情况——当程序员有额外的知识时。如果你知道obj它没有额外的属性,你可以使用文字类型断言。
Tit*_*mir 18
Object.keys返回string[]。如本期所述,这是设计使然
这是故意的。TS中的类型是开放式的。因此keysof可能会小于您在运行时获得的所有属性。
有几种解决方案,最简单的一种是只使用类型断言:
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])[]);
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个别名keys在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])[]);
Run Code Online (Sandbox Code Playgroud)
1. npm install ts-extras (作者:辛德雷索胡斯)import { objectKeys } from 'ts-extras'
objectKeys(yourObject)
Run Code Online (Sandbox Code Playgroud)
就是这样。
这是我在知道之前制作的另一个包ts-extras:
import { objectKeys } from 'ts-extras'
objectKeys(yourObject)
Run Code Online (Sandbox Code Playgroud)
import { ObjectTyped } from 'object-typed'
ObjectTyped.keys({ a: 'b' })
Run Code Online (Sandbox Code Playgroud)
这将返回一个类型的数组['a']
小智 6
请参阅https://github.com/microsoft/TypeScript/issues/20503。
declare const BetterObject: {
keys<T extends {}>(object: T): (keyof T)[]
}
const icons: IconName[] = BetterObject.keys(IconMap)
Run Code Online (Sandbox Code Playgroud)
将保留键的类型而不是 string[]
我完全不同意 Typescript 团队的决定......
按照他们的逻辑,Object.values应该总是返回 any,因为我们可以在运行时添加更多属性......
我认为正确的方法是创建具有可选属性的接口并在您进行时设置(或不设置)这些属性......
因此,我ObjectConstructor通过向我的项目添加一个声明文件(又名:whatever.d.ts)来简单地在本地覆盖接口,其中包含以下内容:
declare interface ObjectConstructor extends Omit<ObjectConstructor, 'keys' | 'entries'> {
/**
* Returns the names of the enumerable string properties and methods of an object.
* @param obj Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
keys<O extends any[]>(obj: O): Array<keyof O>;
keys<O extends Record<Readonly<string>, any>>(obj: O): Array<keyof O>;
keys(obj: object): string[];
/**
* Returns an array of key/values of the enumerable properties of an object
* @param obj Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries<T extends { [K: Readonly<string>]: any }>(obj: T): Array<[keyof T, T[keyof T]]>
entries<T extends object>(obj: { [s: string]: T } | ArrayLike<T>): [string, T[keyof T]][];
entries<T>(obj: { [s: string]: T } | ArrayLike<T>): [string, T][];
entries(obj: {}): [string, any][];
}
declare var Object: ObjectConstructor;
Run Code Online (Sandbox Code Playgroud)
Object.keys/Object.entries 的原始类型(object)将返回 never[] 和 [never, never][] 而不是普通的 string[] 和 [string, any][]。如果有人知道解决方案,请随时在评论中告诉我,我将编辑我的答案
const a: {} = {};
const b: object = {};
const c: {x:string, y:number} = { x: '', y: 2 };
// before
Object.keys(a) // string[]
Object.keys(b) // string[]
Object.keys(c) // string[]
Object.entries(a) // [string, unknown][]
Object.entries(b) // [string, any][]
Object.entries(c) // [string, string|number][]
// after
Object.keys(a) // never[]
Object.keys(b) // never[]
Object.keys(c) // ('x'|'y')[]
Object.entries(a) // [never, never][]
Object.entries(b) // [never, never][]
Object.entries(c) // ['x'|'y', string|number][]
Run Code Online (Sandbox Code Playgroud)
因此,请谨慎使用它...
| 归档时间: |
|
| 查看次数: |
10638 次 |
| 最近记录: |