[英]Typescript: Infer generic type by checking string value
我有這樣的類型:
export type NotificationType = 'comment' | 'like' | 'message' | 'follow' | unknown
type MessageBody<T extends NotificationType> = T extends 'comment'
? {
body: string
threadId: string
projectId: string
}
: T extends 'like'
? {
resourceId: string
resourceType: 'project' | 'projectVersion' | 'thread' | 'comment'
}
: T extends 'message'
? {
body: string
chatId: string
}
: T extends 'follow'
? {}
: never
export type Message<T extends NotificationType = unknown> = {
channel: string
message: MessageBody<T> & {
type: T
}
timetoken: string | number
uuid?: string
publisher?: string
}
我現在想做的是通過檢查屬性message.type
來推斷T
的類型,而不必事先指定T
的類型,就像這樣:
function checkMessage(message: Message) { // No generic type given
switch (message.message.type) {
case 'comment':
message.message.body // infers to MessageBody<'comment'>
}
}
但是通過這種方法,我在 switch 語句中收到錯誤消息: Property 'type' does not exist on type 'never'.
這可能來自NotificationType
中對unknown
的使用。 我怎樣才能擁有通用可選並仍然通過檢查字符串來推斷類型?
我敢打賭NotificationType
應該只是一個字符串。 因此,使用unknown
並不是表示未知字符串類型的最佳選擇。 最好只使用 refular string
類型。 但是,將string
類型與其他文字字符串(如comment
和follow
)一起使用會將它們沖突為string
。 這就是為什么 t 最好使用string & {}
的原因。
另外,我使用了 map 數據結構而不是條件類型MessageBody
。
export type KnownType = 'comment' | 'like' | 'message' | 'follow'
export type UnknownType = string & {}
type NotificationType = KnownType | UnknownType
type MessageMap = {
comment: {
body: string
threadId: string
projectId: string
},
like: {
resourceId: string
resourceType: 'project' | 'projectVersion' | 'thread' | 'comment'
},
message: {
body: string
chatId: string
},
follow: {}
}
type MessageBase = {
channel: string
timetoken: string | number
uuid?: string
publisher?: string
}
type MessageBody<T extends KnownType> = { message: MessageMap[T] & { type: T } } & MessageBase
export type ComputeMessage<T extends NotificationType> = T extends KnownType ? MessageBody<T> : never
function checkMessage<MessageType extends NotificationType>(message: ComputeMessage<MessageType>) {
switch (message.message.type) {
case 'comment':
message.message.projectId // ok
message.message.threadId // ok
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.