Как предложить автозаполнение в forwardRef с помощью машинописного текста

#reactjs #typescript

Вопрос:

Я хочу получить доступ к автозаполнению для forwardRef via useImperativeHandle , но typescript не может определить его методы (например, foo, bar, log)

 import * as React from 'react'

const Re = React.forwardRef((_, ref) => {
    React.useImperativeHandle(ref, () => ({
        log: console.log,
        foo: () => 5,
        bar: (num: number) => num   2
    }), [])
    return null
})



const App = () => {
    const ref = React.createRef()
   
    // 🌟 Why we don't have any suggestion here for ref.current
    // ref.current?
    return <Re ref={ref} />

}
 

Игровая площадка для машинописи



Ответ №1:

Typescript может выводить типы только на основе того, что ему уже известно. Он не будет делать выводов на основе того, что произойдет позже в вашем коде.

Тип ref переменной присваивается в момент ее создания с помощью вызова React.createRef() . На данный момент Typescript не знает, что вы собираетесь передать эту ссылку Re компоненту. Таким образом, тип ссылки таков unknown .

Вы должны указать Typescript, какой тип вы хотите, ref чтобы он был в момент его создания. Вы делаете это, установив общий параметр вкл React.createRef() (или React.useRef() ).

 import * as React from "react";

interface MyRef {
  log: typeof console.log;
  foo: () => number;
  bar: (num: number) => number;
}

const Re = React.forwardRef<MyRef, any>((_, ref) => {
  React.useImperativeHandle(
    ref,
    () => ({
      log: console.log,
      foo: () => 5,
      bar: (num: number) => num   2
    }),
    []
  );
  return null;
});

const App = () => {
  const ref = React.createRef<MyRef>();

  const someFunc = () => {
    // ref.current is null | MyRef
    if (ref.current) {
      // ref.current is MyRef
      ref.current.log("hello world");
      ref.current.log(ref.current.bar(9));
    }
  };

  return (
    <div>
      <button onClick={someFunc}>Execute</button>
      <Re ref={ref} />
    </div>
  );
};

export default App;
 

Нажатие кнопки «Выполнить» в этом коде вызывает функции из Re и регистрирует hello world и 11 .

Комментарии:

1. Спасибо за ваше объяснение, есть ли способ сокращенного объявления API, используемого в интерфейсе useImperativeHandler и MyRef. есть ли способ создать интерфейс на основе этого API ?