Сделайте требуемое свойство основанным на другом свойстве интерфейса c - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть интерфейс для компонента реакции. Там есть куча свойств, но я хочу, чтобы одно свойство влияло на другие. Итак, у меня есть:

export interface IMyAwesomeComponentProps<T = {}> {
    className: string
    defaultPath?: ISomeOtherInterface<T>

    // more properties...
    // ...and finally

    isDraggable?: boolean
    onDrag?: () => {}
}

Эта вещь реализована так:

export class MyAwesomeComponent<T> extends React.Component<IMyAwesomeComponentProps<T>> {
   //...
}

Итак, что мне делать, когда я передаю «isDraggable» как «true» ", Я хочу, чтобы" onDrag "был обязательный .

Чтобы решить эту проблему, я сначала исключил функцию" onDrag "из интерфейса и сделал новый тип. Затем я создал тип утилиты, который в основном говорит: «если это« isDraggable »- правда, а затем вернуть интерфейс в сочетании с« TDraggableProps », иначе просто верните мне интерфейс». В целом это выглядит так:

type TDraggableProps = {  
  onDrag: () => void
  // maybe some more props  
}

type Test<I extends ITreeProps> = I['isDraggable'] extends true ? I & TDraggableProps : I

export class MyAwesomeComponent<T> extends React.Component<Test<IMyAwesomeComponentProps<T>>>

А-а-а, это вроде работает, но это не так. И я понятия не имею, что делать с тем универсальным c, который входит в интерфейс.

Ответы [ 3 ]

1 голос
/ 14 апреля 2020

Вы можете использовать Дискриминационный союз

type Props = {
  isDraggable: true;
  onDrag: () => void;
} | {
  isDraggable: false;
}

const Component = (props: Props) => {}

Component({ isDraggable: false }); // Ok
Component({ isDraggable: true }); // Error onDrag is missing
Component({ isDraggable: true, onDrag: () => {} }); // Ok

Если вам нужно добавить некоторые общие реквизиты, вы можете либо сделать типы в качестве интерфейса и расширить некоторый базовый интерфейс, либо просто извлечь их в отдельный тип и присоединяйся к своему реквизиту

type Props = {
  isDraggable: true;
  onDrag: () => void;
} | {
  isDraggable: false;
}

type StaticProps = {
  className: string;
}

const Component = (props: Props & StaticProps) => {}

Component({ isDraggable: false, className: "123" });
Component({ isDraggable: true, className: "123" }); // Error onDrag is missing
Component({ isDraggable: true, onDrag: () => {}, className: "123" }); // Ok
1 голос
/ 14 апреля 2020

Я бы сделал Props типом, затем переместил бы весь интерфейс для всех общих свойств и для различных свойств, я думаю, что этот подход выглядит чистым и читабельным:

interface Common {
  x: number;
  y: number;
  z: number;
}

interface RequiredB {
  a: true;
  b: () => {}
}

interface OptionalB {
  a: false;
  b?: () => {}
}

type Props = Common & (RequiredB | OptionalB);

const obj: Props = {
  x: 1,
  y: 2,
  z: 3,
  //a: false, // b is not required now
  //a: true, // b is required now
}

1 голос
/ 14 апреля 2020

Я бы изменил вашу подпись IMyAwesomeComponentProps вашего интерфейса, создав интерфейс IDraggable и включив его в ваш IMyAwesomeComponentProps. Конечно, если предположить, что ситуация, когда isDraggable = false и onDrag is defined бесполезны ...

Примерно так:

    interface ITest<T = {}> {
    a: string;
    b: IInner<T>;
    isDraggable?: IIsDragble;
}

interface IIsDragble {
    onDrag: () => void;
}

const a: ITest = {
    a: "dsd",
    b: {
        valInner: "ssdds",
    },
};

const b: ITest = {
    a: "dsd",
    b: {
        valInner: "ssdds",
    },
    isDraggable: {
        onDrag: () => true,
    },
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...