我还在学习TypeScript及其拥有的所有功能。其中之一是限制泛型。如果这是一个常见问题我很抱歉,如果你有任何资源(除了文档之外)可以帮助我在这方面做得更好,请链接为评论。
我想要做的是,type
属性与DeliveryObject
和deliveryItems
内的所有对象匹配。
以下是编译代码的示例,但并不是我正在寻找的最终解决方案。
type DeliveryMethod = 'notification' | 'text' | 'email'
type DeliveryActions = INotificationAction | ITextMessageAction | IEmailAction
interface IDelivery {
type: DeliveryMethod
}
interface INotificationAction extends IDelivery {
type: 'notification'
deviceId: string
message: string
}
interface ITextMessageAction extends IDelivery {
type: 'text'
message: string
}
interface IEmailAction extends IDelivery {
type: 'email'
to: string
subject: string
body: string
}
// I know I need to do something additional here...
interface IDeliveryObject<T extends DeliveryMethod, U extends DeliveryActions> {
type: T
deliveryItems: Array<U>
}
function sendDelivery<K extends DeliveryMethod, Z extends DeliveryActions>(state: IDeliveryObject<K, Z>) {
console.log(state)
}
sendDelivery({
type: 'notification', // <--- needs to match or error out
deliveryItems: [
{
type: 'email', // <--- needs to match or error out
to: 'fake@email.com',
subject: '1235-67890',
body: 'Here is a notification'
}
]
})
答案 0 :(得分:2)
我会通过使用“类型查找映射”将传递方法与其关联的操作对象联系在一起来实现此目的。所以我会添加另一种类型:
type DeliveryActionTypes = {
"notification": INotificationAction;
"text": ITextMessageAction;
"email": IEmailAction;
}
该类型只是将正确的方法名称映射到它的操作对象类型。然后,您可以将DeliveryMethod
和DeliveryActions
的声明替换为:
type DeliveryMethod = keyof DeliveryActionTypes;
type DeliveryActions = DeliveryActionTypes[keyof DeliveryActionTypes];
如果您知道方法的名称,那么您可以轻松查找正确的操作。您可以在IDeliveryObject
中使用它来确保两种类型对应:
interface IDeliveryObject<T extends DeliveryMethod> {
type: T;
// This is the type lookup, note the `DeliveryActionTypes[T]` part.
deliveryItems: Array<DeliveryActionTypes[T]>;
}
现在您可以简化sendDelivery
函数的签名,因为它现在需要的只是方法名称:
function sendDelivery<K extends DeliveryMethod>(state: IDeliveryObject<K>) {
console.log(state)
}
尽管如此,如果类型不匹配,您将收到错误:
sendDelivery({
type: 'notification',
deliveryItems: [
{
type: 'email',
to: 'fake@email.com', // <-- error on this line, see below
subject: '1235-67890',
body: 'Here is a notification'
}
]
})
Type '{ type: "email"; to: string; subject: string; body: string; }' is not assignable to type 'INotificationAction'.
正如您所看到的,Typescript正确地断定数组中的项应该是INotificationAction
类型,并且当它们不是时会产生错误。