我有一个这样的函数:

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
}

我try 使用this post中的方法来创建一个变量,该变量可用于循环输入对象的属性,而不管它是哪个接口的实例,但我得到了以下错误:

TS2405: The left-hand side of a 'for...in' statement must be of type 'string' or 'any'.

然而,如果我try 这样定义‘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个函数,每个接口一个?

推荐答案

TypeScrip不会让循环遍历对象的键变得非常容易,这种方式允许您使用这些键进行索引,如How to iterate over keys of a generic object in TypeScript?中所述.答案中的大多数技术适用于不同的用例,但这里使用的具有union个接口的技术不起作用,因为在联合上操作时,the keyof operator会提供intersection个键,这意味着只有all中出现的键是联合成员.这是编译器所做的最安全的事情,但是它忘记了对象类型和它的键之间的correlation.

该语言不能以任意的方式处理联合类型的使用;一般问题在microsoft/TypeScript#30581中进行了描述.如果您想要执行适用于类型联合的单个操作,则可以重构为使用generics(这是第microsoft/TypeScript#47109中描述的MS/TS#30581解决方案的一部分):

function myFunc<T extends A | B | C>(input: T) {
  let key: keyof T;
  for (key in input) {
    let temp = input[key]; // okay
    //  ^? let temp: T[keyof T]
    console.log(temp);
  }
}

您可以采取的另一种方法是将输入类型从A | B | C扩大到类型Record<string, any>或等效的{[k: string]: any}.此类型的值为index signature,表示它将允许任何键,并且该键的属性类型被故意指定为宽松的any type:

function myFunc(_input: A | B | C) {
  const input: { [k: string]: any } = _input;
  for (const key in input) { 
    let temp = input[key]; // okay
    //  ^? any
    console.log(temp);
  }
}

这两种方法都不是完美的.根据您的需要,您可能希望放弃for...in循环,转而使用the Object.entries() method,它同时为您提供键和值:

function myFunc(input: A | B | C) {
  Object.entries(input).forEach(([key, temp]) => {
    temp
    // ^? any
    console.log(temp);
  })
}

Playground link to code

Javascript相关问答推荐

在JavaScript中对大型级联数组进行切片的最有效方法?

如何在不分配整个数组的情况下修改包含数组的行为主体?

*ngFor和@代表输入decorator 和选角闭合

我无法在NightWatch.js测试中获取完整的Chrome浏览器控制台日志(log)

硬币兑换运行超时

Chart.js V4切换图表中的每个条,同时每个条下有不同的标签.怎么做?

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

为什么!逗号和空格不会作为输出返回,如果它在参数上?

html + java script!需要帮助来了解为什么我得到(无效的用户名或密码)

JS,当你点击卡片下方的绿色空间,而它是在它的背后转动时,

以Angular 实现ng-Circle-Progress时出错:模块没有导出的成员

无法避免UV:flat的插值:非法使用保留字"

将范围 Select 器添加到HighChart面积图

如何使用抽屉屏幕及其子屏幕/组件的上下文?

如何在AG-Grid文本字段中创建占位符

postman 预请求中的hmac/sha256内标识-从js示例转换

从异步操作返回对象

如何使用fltter_js将对象作为参数传递给javascrip?

使用VITE开发服务器处理错误

为什么我的Reaction组件不能使用createBrowserRouter呈现?