簡體   English   中英

Typescript:通過檢查字符串值推斷通用類型

[英]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類型與其他文字字符串(如commentfollow )一起使用會將它們沖突為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM