Какой тип машинописи я использую с ловушкой useRef () при ручной настройке current? - PullRequest
2 голосов
/ 19 сентября 2019

Как я могу использовать React ref как изменяемый экземпляр с Typescript?Похоже, что текущее свойство имеет тип только для чтения.

Я использую React + Typescript для разработки библиотеки, которая взаимодействует с полями ввода, которые НЕ отображаются в React.Я хочу захватить ссылку на элемент HTML, а затем привязать к нему события React.

  const inputRef = useRef<HTMLInputElement>();
  const { elementId, handler } = props;

  // Bind change handler on mount/ unmount
  useEffect(() => {
    inputRef.current = document.getElementById(elementId);
    if (inputRef.current === null) {
      throw new Exception(`Input with ID attribute ${elementId} not found`);
    }
    handler(inputRef.current.value);

    const callback = debounce((e) => {
      eventHandler(e, handler);
    }, 200);

    inputRef.current.addEventListener('keypress', callback, true);

    return () => {
      inputRef.current.removeEventListener('keypress', callback, true);
    };
  });

Он генерирует ошибки компилятора: semantic error TS2540: Cannot assign to 'current' because it is a read-only property.

Я также пытался const inputRef = useRef<{ current: HTMLInputElement }>(); Это приводит к этой ошибке компилятора:

Type 'HTMLElement | null' is not assignable to type '{ current: HTMLInputElement; } | undefined'.

  Type 'null' is not assignable to type '{ current: HTMLInputElement; } | undefined'.

1 Ответ

2 голосов
/ 20 сентября 2019

Да, это извращение того, как пишутся наборы:

function useRef<T>(initialValue: T): MutableRefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T>;

Если начальное значение включает null, а указанный параметр типа - нет, он будет рассматриваться какнеизменный RefObject.

Когда вы делаете useRef<HTMLInputElement>(null), вы попадаете в этот случай, поскольку T задается как HTMLInputElement, а null выводится как HTMLInputElement | null.

Вы можетеисправьте это, выполнив:

useRef<HTMLInputElement | null>(null)

Тогда T будет HTMLInputElement | null, что соответствует типу первого аргумента, поэтому вы нажмете первое переопределение и получите вместо него изменяемый ref.

...