본문 바로가기

개발하자

Typescript 일반 JSX 인수와 함께 React forwardRef 사용

반응형

Typescript 일반 JSX 인수와 함께 React forwardRef 사용

다음과 같은 유형의 리액트 구성요소를 사용할 경우 리액트의 새로운 API로 포장하려면 어떻게 해야 합니까?

type Props<T> = {
  forwardedRef?: Ref<HTMLInputElement>
  ...
}

class GenericComponent<T> extends Component<Props<T>> {
  ...
}

const ComponentWithRef = forwardRef<HTMLInputElement, Props<T>>((props, ref) => (
  <StringInput<T> {...props} forwardedRef={ref} />
))

위의 접근법은 제네릭을 정의할 방법이 없다.




따라서, 질문을 좀 더 넓히기 위해, 이것은 실제로 더 높은 차수의 함수에서 제네릭 타입을 보존하는 것에 대한 질문이다. 의 다음 사용법은 체크를 적절히 입력합니다(에서)

const SelectWithRef = forwardRef(<Option extends string>(props: Props<Option>, ref?: Ref<HTMLSelectElement>) =>
  <Select<Option> {...props} forwardedRef={ref} />);

그러나 제네릭은 제네릭으로 남아있지 않고 즉시 로 해결된다. 이와 같이, 다음은 체크를 타이핑하지 않는다

const onChange: (value: 'one' | 'two') => void = (value) => console.log(value);

<SelectWithRef<'one' | 'two'>
              ^^^^^^^^^^^^^^^ [ts] Expected 0 type arguments, but got 1
  value="a"
  options={['one', 'two']}
  onChange={onChange}
           ^^^^^^^^^^ [ts] Type 'string' is not assignable to type '"one" | "two"'
/>

관련 문제는 에서 추적합니다.




다음과 같은 해결책이 있다고 생각합니다:

type Props<T> = {
    ref?: MutableRefObject<HTMLDivElement | null>;
    someProp: string; 
    testType: T;
}

const TestComponent: <T extends any>(props: Props<T>) => ReactNode = (() => {
    // eslint-disable-next-line react/display-name
    return forwardRef(({someProp, testType}, ref: ForwardedRef<HTMLDivElement>) => {
        console.log(someProp, testType);
        return <div ref={ref}>testasd</div>;
    });
})();

그 다음:

type TestType = {
    name: string;
};

const SomePage: FC = () => {
    const someRef = useRef<HTMLDivElement | null>(null);
    return (
        <div>
            <TestComponent<TestType> someProp='OK' ref={someRef} testType={{name: 'test'}}/>
        </div>
    );
};

이것은 오류 없이 컴파일된다.

의 유형이 정확하게 추론되다

다음에 오류가 발생합니다:

<TestComponent<TestType> someProp='ERROR' ref={someRef} testType={'test'}/>

Type 'string' is not assignable to type 'TestType'.ts(2322)

예상되는 바입니다.


반응형