TypeScript:使用名称未知的字段声明类型或接口

问题描述

我必须声明一个团队对象的接口:

export interface Team{
  memberUid?: {
    mail: string
    name: string
    photoURL: string
  }
  startDate: Timestamp
  endDate: Timestamp
  agenda: Array<{
    date: Date | Timestamp
    title: string
    description: string
  }>
}

将有几个成员Uid。我不知道如何在TypeScript中声明它。

我尝试过:

[memberUid: string] : {
  mail: string
  name: string
  photoURL: string
}

但是TypeScript理解Team中的所有字段都应该具有这种结构。

处理此问题的正确方法是什么?

谢谢

解决方法

首先让我说我讨厌这种结构。如果有一种方法可以将您的代码重写为更具逻辑性的Team类型,请执行此操作。但是可以做到吗?是的,它可以。 Team必须是type而不是接口,因为接口只能具有已知键。

让我们先将其分解成碎片。

TeamBase定义了始终存在的属性:

interface TeamBase {
  startDate: Timestamp
  endDate: Timestamp
  agenda: Array<{
    date: Date | Timestamp
    title: string
    description: string
  }>
}

UidProperties定义未知密钥的内容:

interface UidProperties {
    mail: string
    name: string
    photoURL: string
}

这是一种实用程序类型,可用于通过使用映射类型基于键的类型来声明属性:

type HasProperty<Key extends keyof any,Value> = {
    [K in Key]: Value;
}

如果通用的Key是字符串文字,那么K in Key的唯一可能的值就是那个确切的字符串,因此HasProperty<"myKey",string>解析为{ myKey: string; }

因此,现在我们需要定义类型Team。我们知道它需要包含TeamBase的所有属性,并且我们知道有一些值为UidProperties的字符串键。以前导致您遇到问题的一个重要事实是,该密钥不能是TeamBase的密钥之一。因此,我们使用string而不是使用Exclude<string,keyof TeamBase>

您可以使用HasProperty<...>来说明不是TeamBase密钥的每个字符串密钥的值为UidProperties,但我认为使用{ {1}}表示这些未知字符串键中的任何一个都可以是Partial<HasProperty<...>>,但也可以是UidProperties。当您访问未知密钥时,您可能还是要仔细检查该值。

因此,我们团队的最终类型是:

undefined

这按预期工作。因为我们允许未定义export type Team = TeamBase & Partial<HasProperty<Exclude<string,keyof TeamBase>,UidProperties>> 的可能性,所以如果不通过与uiduid的可选链接排除undefined,就不能访问?的属性。声明等。

if

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...