Как заставить проверку типов работать с React forwardRef

avatar
Aaron
8 августа 2021 в 17:04
157
2
1

У меня возникли проблемы с проверкой типов при использовании forwardRef. Мой код выглядит следующим образом:

Компонент:

export interface Props {
  label?: string;
  callback: () => void;
}

export const _Button = (props: Props) => {

  return (
    <div>
      <p>test</p>
    </div>
  );
};

export const Button = React.forwardRef((props, ref) => {
  return <_Button { ...props } forwarded={ref} />
});

Использование компонента:

export const App = () => {

  return (
    <div>
      <h1>Application</h1>
      <Button label="foo" />
    </div>
  );
};

Вы можете видеть, что я не передаю требуемую поддержку обратного вызова, но машинописный текст не видит проблемы. Ниже показано, что я пробовал, и я все еще не могу заставить работать проверку типов.

export interface Props {
  label?: string;
  callback: () => void;
}

export const _Button = (props: Props) => {

  return (
    <div>
      <p>test</p>
    </div>
  );
};

export const Button = React.forwardRef<HTMLButtonElement, Props>((props: Props, ref) => {
  return <_Button { ...props } forwarded={ref} />
});

Будем признательны за любую помощь. Спасибо.

Добавлено изображение для ответа на ответы 1 и 2. Ожидается, что это ошибка машинописного текста.

enter image description here

Источник

Ответы (2)

avatar
captain-yossarian
9 августа 2021 в 08:06
0

Я предполагаю, что вы хотите сделать что-то вроде этого:

import React, { FC, forwardRef, ForwardedRef, createRef } from 'react'

export interface Props {
    label?: string;
    callback: () => void;
    forwardedRef: ForwardedRef<HTMLDivElement>
}

export const _Button: FC<Props> = (props: Props) => {


    return (
        <div ref={props.forwardedRef}>
            <p>test</p>
        </div>
    );
};

export const Button = forwardRef<
    HTMLDivElement,
    Omit<Props, 'forwardedRef'>
>((props, ref) => <_Button {...props} forwardedRef={ref} />);


export const App = () => {
    const ref = createRef<HTMLDivElement>();

    return (
        <div>
            <h1>Application</h1>
            <Button ref={ref} label="foo" callback={() => null} />
        </div>
    );
};

Здесь вы можете найти документацию по ссылкам.

Aaron
9 августа 2021 в 15:12
0

Я ценю ответ. Я все еще не получаю ошибку машинописного текста, когда мне не удается добавить требуемый обратный вызов реквизита. Используя ваш код, если я сразу экспортирую _Button и обхожу forwardRef и удаляю: React.FC<Props>, проверка машинописного текста работает. Я включил изображение того, о чем я говорю, в конце моего первоначального поста. Как видите, вместо этого я экспортировал _Button, и проверка типов работает. Я до сих пор не могу заставить его работать ни с одним из ответов выше.

captain-yossarian
9 августа 2021 в 15:17
0

Вы должны указать свойства callback и forwarderRef для _Button.

captain-yossarian
9 августа 2021 в 15:24
0

@Aaron, пожалуйста, поделитесь на игровой площадке ts примером с ошибкой

Aaron
9 августа 2021 в 23:50
0

Это странно, проверка типов работает правильно в песочнице кода, как я и ожидал, даже мой код работал правильно. Однако на моей локальной машине с использованием VSCode и Intelij проверка типов не показывает ошибку, когда я не могу добавить требуемую опору. Возможно, это проблема редактора. В песочнице кода я использовал ваш код и сделал требуемую метку, и ошибка машинописного текста отображается, как и ожидалось. codesandbox.io/s/staging-surf-kodow?file=/src/App.tsx

Aaron
10 августа 2021 в 01:48
0

если у вас есть возможность, посмотрите на песочницу. Я сбит с толку тем, почему я не могу получить машинописный текст, чтобы показать ошибку, когда я не добавляю необходимые реквизиты.

captain-yossarian
10 августа 2021 в 07:44
0

Извините, я немного запутался. Что вы ожидаете? Я вижу ошибку в codeandbox Property 'label' is missing in type '{ callback: null; }' but required in type 'Pick<Props, "label" | "callback">'. Вы хотите исправить эту ошибку?

Aaron
10 августа 2021 в 14:22
0

Да, я тоже это вижу, это работает в любом из моих редакторов, включая intellij и VSCode. Не знаю, это немного расстраивает. Спасибо за вашу помощь.

avatar
slideshowp2
9 августа 2021 в 08:23
0

Вы переданы ref по реквизитам _Button. Вы должны объявить реквизит forwarded для компонента _Button с типом: React.Ref<HTMLDivElement>.

type Ref<T> = RefCallback<T> | RefObject<T> | null;
import React from 'react';

export interface Props {
  label?: string;
  callback: () => void;
  forwarded: React.Ref<HTMLDivElement>;
}

export const _Button = (props: Props) => {
  return (
    <div>
      <p>test</p>
    </div>
  );
};

export const Button = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
  return <_Button {...props} forwarded={ref} />;
});

версии пакетов:

"typescript": "^4.0.3",
"react": "^17.0.1",
Aaron
9 августа 2021 в 15:16
0

Я ценю ответ. Я все еще не получаю ошибку машинописного текста, когда мне не удается добавить требуемый обратный вызов реквизита. Используя ваш код, если я сразу экспортирую _Button и обхожу forwardRef, проверка машинописного текста работает. Я включил изображение того, о чем я говорю, в конце моего первоначального поста. Как видите, вместо этого я экспортировал _Button, и проверка типов работает. Я до сих пор не могу заставить его работать ни с одним из ответов здесь.