NodeJS 如何循环遍历一个参数的键,该参数可以是TypeScript中3个不同接口之一?

hwamh0ep  于 5个月前  发布在  Node.js
关注(0)|答案(1)|浏览(73)

我有一个这样的函数:

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个函数,每个接口一个?

wxclj1h5

wxclj1h51#

TypeScript并不容易循环对象的键,让你用这些键索引,就像How to iterate over keys of a generic object in TypeScript?中描述的那样。那里的答案中的大多数技术适用于各种用例,但是你在这里用一个接口的联合不会工作,因为keyof操作符在作用于联合时给出了键的交集,这意味着仅仅是出现在 * 所有 * 联合成员中的键。这是编译器最安全的做法,但是它会丢失对象类型和它的键之间的 * 相关性 *。
该语言无法真正处理以任意方式使用联合类型; 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}。这种类型有一个索引签名,意味着它将允许任何键,并且该键处的属性类型被故意赋予宽松的any类型:

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链接到代码

相关问题