问题描述
我必须声明一个团队对象的接口:
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>>
的可能性,所以如果不通过与uid
或uid
的可选链接排除undefined
,就不能访问?
的属性。声明等。
if