我有一个这样的函数:
function myFunc(input: A | B | C) {
let key: keyof A | keyof B | keyof C;
for(key in input)
{
let temp = input[key];
console.log(temp);
}
}
字符串
其中A B和C的定义如下:
interface A {
u: number,
t: string,
s: boolean,
r: boolean
}
interface B {
w: string,
v: string
}
interface C {
z: string,
y: number,
x: boolean
}
型
我尝试使用this post中的方法来创建一个变量,该变量可用于循环输入对象的属性,而不管它是哪个接口的示例,但我得到了以下错误:
TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.
型
但是,如果我尝试像这样定义“key”:
let key:any;
型
我得到一个不同的错误:
TS7053: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'A | B | C'.
型
有没有一种方法来定义“key”,这样我就可以把它变成一个函数,或者我必须把它分成3个函数,每个接口一个?
1条答案
按热度按时间wxclj1h51#
TypeScript并不容易循环对象的键,让你用这些键索引,就像How to iterate over keys of a generic object in TypeScript?中描述的那样。那里的答案中的大多数技术适用于各种用例,但是你在这里用一个接口的联合不会工作,因为
keyof
操作符在作用于联合时给出了键的交集,这意味着仅仅是出现在 * 所有 * 联合成员中的键。这是编译器最安全的做法,但是它会丢失对象类型和它的键之间的 * 相关性 *。该语言无法真正处理以任意方式使用联合类型; microsoft/TypeScript#30581中描述了一般问题。如果您想执行适用于类型联合的单个操作,则可以重构为使用generics(这是microsoft/TypeScript#47109中描述的ms/TS#30581解决方案的一部分):
字符串
另一种方法是将输入类型从
A | B | C
扩展到Record<string, any>
或等价的{[k: string]: any}
。这种类型有一个索引签名,意味着它将允许任何键,并且该键处的属性类型被故意赋予宽松的any
类型:型
这两种方法都不是完美的。根据你的需要,你可能想给予放弃
for...in
循环,而使用theObject.entries()
method,它同时给你键和值:型
Playground链接到代码