typescript - Ayrımcı olarak enum kullanılan ayrımcı birleşimi nasıl kullanılır


Bir diskriminatörün bir enum olduğu ve enum alanının değerinin başka bir alanın tanımsız olup olmadığını belirlediği bir ayrılmış birleşimim var. Şöyle ki:

enum Status {
  TOP, BOTTOM, MIDDLE
}
type StatusReport = 
| {
  status: Status.TOP | Status.BOTTOM
  message: undefined
} 
| {
  status: Status.MIDDLE
  message: string
}

Her şey yolunda. Şimdi uygun parametrelerden bu türü oluşturacak bir fonksiyon tanıtıyorum:

function statusReporter(theStatus: Status, statusMessage:string):StatusReport{
  return {
    status: theStatus,
    message: theStatus === Status.MIDDLE ? statusMessage : undefined
  }
}

Bu fonksiyon mantığı bana sağlam görünüyor. status'ta ayarlanan enum değerine bağlı olarak message'e doğru değeri atayacak. Ama TS, Status'ın type Status.MIDDLE türüne atanamayacağını belirten hatalar veriyor. Bu tabii ki doğru, ama bence koşulum bunun olmasını engelliyor.

Neden bu hatayı alıyorum ve çözümü nedir?

İşte oyun alanı

theStatus'in türünü theStatus'in Status.MIDDLE'yi genişletip genişletmediğine bağlı olarak bir koşullu tür olarak belirtmeyi denedim (status: theStatus as typeof theStatus extends Status.MIDDLE ? Status.MIDDLE : Status), ama faydası olmadı. Aynı hatayı alıyorum.

Cevap #1

Nesnenizi oluşturmadan önce türü belirlemeniz gerekir.

function statusReporter(theStatus: Status, statusMessage:string):StatusReport{
  return theStatus === Status.MIDDLE ? {
    status: theStatus,
    message: statusMessage
  } : {
    status: theStatus,
    message: undefined
  }
}

Oyun alanı linki

Cevap #2

Fonksiyon aşırı yüklemesini kullanmanız gerekiyor:

enum Status {
  TOP, BOTTOM, MIDDLE
}

type WithoutMessage = {
  status: Status.TOP | Status.BOTTOM
  message: undefined
}
type WithMessage = {
  status: Status.MIDDLE
  message: string
}

type StatusReport = WithMessage | WithoutMessage


function statusReporter(theStatus: Status.MIDDLE, statusMessage: string): WithMessage
function statusReporter(theStatus: Exclude<Status, Status.MIDDLE>, statusMessage: string): WithoutMessage
function statusReporter(theStatus: Status, statusMessage: string): StatusReport
function statusReporter(theStatus: Status, statusMessage: string) {
  return {
    status: theStatus,
    message: theStatus === Status.MIDDLE ? statusMessage : undefined
  }
}

function builder(myStatus: Status) {
  return statusReporter(myStatus, "hello");
};
const hof = builder(Status.MIDDLE) // StatusReport

const result = statusReporter(Status.MIDDLE, 'hello') // WithMessage
const result2 = statusReporter(Status.BOTTOM, 'hello') // WithoutMessage
const result3 = statusReporter(Status.TOP, 'hello') // WithoutMessage

Oyun alanı

Bu hatayı alıyorsunuz çünkü message özelliği string | undefined olarak değerlendiriliyor, oysa StatusReportundefined ya da message bekliyor, ama ikisini birden değil, yani birleşimi değil

GÜNCELLEME

function statusReporter(theStatus: Status, statusMessage: string): StatusReport {
  if (theStatus === Status.MIDDLE) {
    return {
      status: theStatus,
      message: statusMessage
    }
  }
  return {
    status: theStatus,
    message: undefined
  }
}