typescript - TypeScript:使用未知名称的字段声明类型或接口
问题描述
我必须为团队对象声明一个接口:
export interface Team{
memberUid?: {
mail: string
name: string
photoURL: string
}
startDate: Timestamp
endDate: Timestamp
agenda: Array<{
date: Date | Timestamp
title: string
description: string
}>
}
会有几个成员 Uids。我不知道如何在 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
,但我认为最好使用Partial<HasProperty<...>>
表示这些未知字符串键中的任何一个可能是UidProperties
但也可能是undefined
。当您访问未知密钥时,您可能无论如何都需要仔细检查该值。
所以我们最终的 Team 类型是:
export type Team = TeamBase & Partial<HasProperty<Exclude<string, keyof TeamBase>, UidProperties>>
这按预期工作。因为我们已经允许未定义的可能性,所以如果不通过可选链接 with或语句等排除uid
,您就不能访问属性。uid
undefined
?
if
function f1(team: Team) {
const startDate: Timestamp = team.startDate;
const uid: UidProperties | undefined = team['randomKey']
const name = uid?.name;
if ( uid !== undefined ) {
const mail = uid.mail;
}
}
推荐阅读
- qt - 如何自动缩放 Qml 地图以适合两个 MapQuickItems
- r - 根据多个条件更改数据表行的颜色
- python - 具有多行的 Pandas read_table 列
- prometheus - 我们如何编写警报规则与普罗米修斯警报规则的先前值进行比较
- azure - Azure B2C 自定义策略 - ID/访问令牌未通过刷新令牌获取最新声明
- python - 为什么在 LightGBM 中使用不同方法分割数据时模型精度不同?
- xamarin - 如何使用 Xamarin 检测硬件变化(sim Change)
- r - R中的for循环中的for循环
- reactjs - 为什么使用 fetch 和 settingState 响应的组件方法不会导致 componentDidMount()?
- docker - Docker 没有运行某些 RUN 指令?