如何在“noImplicitAny”检查激活的情况下重写in循环的typescript?

问题描述 投票:1回答:2

我有一些声明的数据接口:

export interface RegisterData {
    email: string
    password: string
    firstName?: string
    lastName?: string
}

并且想要创建和对象只有接口实例的非空字段(并避免一些非空的特殊字段,如密码):

const nonEmptyData: any = { };

for(const itemId in registerData) {
  if(itemId !== "password" && registerData[itemId]) {
    nonEmptyData[itemId] = registerData[itemId];
  }
}

但是,如果“noImplicitAny”检查处于活动状态,我会收到下一个错误:

error TS7017: Element implicitly has an 'any' type because type 'RegisterData' has no index signature.

如果'for in'可用于检查有效吗?

typescript typescript2.0
2个回答
3
投票

你可以使用Object.keys断言key数组实际上是RegisterData的一个键数组:

for (const itemId of Object.keys(registerData) as Array<keyof RegisterData>) {
    if (itemId !== "password" && registerData[itemId]) {
        nonEmptyData[itemId] = registerData[itemId];
    }
}

添加索引签名也是一个选项,但不是一个很好的选项,允许通过任何字符串进行索引。

编辑

或者更好的是,根据您的目标和polyfills,您也可以使用Object.entries

for (const [itemId, value] of Object.entries(registerData)) {
    if (itemId !== "password" && value) {
        nonEmptyData[itemId] = value;
    }
}

1
投票

您可以扩展添加索引签名的接口以在需要时进行迭代:

interface IterableRegisterData extends RegisterData {
  [key: string]: string | undefined
}

const iterableRegisterData = registerData as IterableRegisterData;
for(const itemId in iterableRegisterData) {
  if(itemId !== "password" && iterableRegisterData[itemId]) {
    nonEmptyData[itemId] = iterableRegisterData[itemId];
  }
}

如果你不需要在循环中改变registerData,你可以在索引签名上添加readonly以防止向iterableRegisterData添加新属性:

interface IterableRegisterData extends RegisterData {
  readonly [key: string]: string | undefined
}

原始答案(不良做法)

只需添加索引签名:

export interface RegisterData {
    email: string
    password: string
    firstName?: string
    lastName?: string
    [key: string]: string | undefined
}

请注意,必须使用联合类型,因为某些属性可能未定义。如果添加更多具有不同类型的属性,则必须将这些类型添加到索引签名:

export interface RegisterData {
    email: string
    age: number
    name?: string
    data: AdditionalData
    [key: string]: string | number | AdditionalData | undefined
}

警告

正如评论中所指出的,这可能是一种不好的做法,因为添加索引签名将允许您添加未在界面中定义的新属性,并且您可能不希望这样:

const userData: RegisterData = { 
    email: '[email protected],
    password: '1234'
}
userData['foo'] = 'baz'
© www.soinside.com 2019 - 2024. All rights reserved.