Тип объединения TypeScript DeepMap с инструкцией if

#javascript #typescript #if-statement #union-types

#javascript #машинописный текст #if-оператор #типы соединений

Вопрос:

Я пытаюсь создать тип объединения со структурой необязательных полей. Я создал следующие типы:

 export type StartEndType = {
  start_date: string;
  end_date: string;
};

export type PayrollContract = StartEndType amp; {
  type: 'ON_PAYROLL';
  yearly_holidays: number;
};

export type FreelanceContract = StartEndType amp; {
  type: 'FREELANCE';
  hourly_rate: number;
};

export type Contract = PayrollContract | FreelanceContract;
 

В моем компоненте это выглядит так:

 {contractType === 'ON_PAYROLL' ? (
  <Number name="yearly_holidays"  />
) : contractType === 'FREELANCE' amp;amp; (
  <Number name="hourly_rate" />
)}
 

Когда я навожу курсор на контракт, он знает, что это один из ON_PAYROLL или FREELANCE . Хотя, к сожалению, я получаю ошибку DeepMap в моем компоненте.

Разве это не поддерживается TypeScript из коробки?

 Property 'yearly_holidays' does not exist on type 'DeepMap<PayrollContract, FieldError> | DeepMap<FreelanceContract, FieldError>'.
  Property 'yearly_holidays' does not exist on type 'DeepMap<FreelanceContract, FieldError>'.
 

Как я могу решить эту проблему?
Заранее спасибо.

Ответ №1:

Не могли бы вы предоставить код для Number компонента? Похоже, проблема в том, как вы отображаете число по имени, я смог скомпилировать и использовать приведенный выше код TS в TS playground.

 const renderPayField = (contract: Contract) => {
  if (contract.type === 'ON_PAYROLL') {
     return <Number name="yearly_holidays" />;
  }
  if (contract.type === 'FREELANCE') {
     return <Number name="hourly_rate" />
  }
  return null;
};

 

Кроме того, обновлены некоторые TS для использования интерфейсов только для чтения, чтобы улучшить читаемость

 export interface StartEndDate {
  start_date: string;
  end_date: string;
};

export interface PayrollContract extends StartEndDate {
  readonly type: 'ON_PAYROLL';
  yearly_holidays: number;
};

export interface FreelanceContract extends StartEndDate {
  readonly type: 'FREELANCE';
  hourly_rate: number;
};

export type Contract = PayrollContract | FreelanceContract;