接口与等效对象的处理方式不同

在下面的代码段中,末尾的两条看似相等的行显然不是。我想以这样一种方式编写函数定义:既不给出错误,都返回<nav class='navigation'> <div></div> <div></div> <div></div> </nav> <section class='one'></section> <section class='two'></section> <section class='three'></section>。有什么想法吗?

(string | number)[]

倒数第二行的错误是:

  

类型'O'的参数不能分配给类型'记录'的参数。

     

类型'O'中缺少索引签名。(2345)

Here it is in the typescript playground

修改 请注意,这是一个简化的示例。保持对可分配给function keyableValues<T extends Record<any,keyof any>>(o: T): T[keyof T][] { const values: T[keyof T][] = []; for (const key of Object.getOwnPropertyNames(o)) { values.push(o[key as keyof T]); } return values; }; interface O { a: string; b: number; } let asInterface: O = { a: 'hi',b: 2 }; const notAsInterface = { a: 'hi',b: 2 }; keyableValues(asInterface); // <- typing error,returns (string | number | symbol)[] keyableValues(notAsInterface); // <- no error,returns (string | number)[] 的值的限制很重要。我真正的用例是一个将集合中的值映射到新对象的键的函数:

keyof any
shala1204 回答:接口与等效对象的处理方式不同

无论好坏,接口类型都不会获得隐式索引签名,而类型别名却会得到。有关更多信息,请参见相关的GitHub问题microsoft/TypeScript#15300

我的建议是改用自引用泛型约束,其中T extends Record<keyof T,...>,对于任何对象类型,无论是接口还是类型别名,都应为true。像这样:

function keyableValues<T extends Record<keyof T,keyof any>>(o: T): T[keyof T][] {
    const values: T[keyof T][] = [];
    for (const key of Object.getOwnPropertyNames(o)) {
        values.push(o[key as keyof T]);
    }
    return values;
};

那应该解决问题:

keyableValues(asInterface);    // <- no error,returns (string | number)[]
keyableValues(notAsInterface); // <- no error,returns (string | number)[]

好的,希望能有所帮助。祝你好运!

Link to code

,

您无需为此使用Recordkeyof就足够了。

function keyableValues<T>(o: T): T[keyof T][] {
    const values: T[keyof T][] = [];
    for (const key of Object.getOwnPropertyNames(o)) {
        values.push(o[key as keyof T]);
    }
    return values;
};

interface O {
    a: string;
    b: number;
}
let asInterface: O = { a: 'hi',b: 2 };

let result = keyableValues(asInterface);

然后将result的类型推断为(string | number)[]

本文链接:https://www.f2er.com/3155368.html

大家都在问