在下面的代码段中,末尾的两条看似相等的行显然不是。我想以这样一种方式编写函数定义:既不给出错误,都返回<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
答案 0 :(得分:1)
无论好坏,接口类型都不会获得隐式索引签名,而类型别名却会得到。有关更多信息,请参见相关的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)[]
好的,希望能有所帮助。祝你好运!
答案 1 :(得分:0)
您无需为此使用Record
; keyof
就足够了。
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)[]
。