ReactJS и Typescript: относится к значению, но здесь используется как тип (TS2749) - PullRequest
0 голосов
/ 28 мая 2020

Я кодирую класс ReactJS с помощью Typescript и Material-ui в файле .tsx. В одном из моих пользовательских компонентов я хочу создать ссылку на один из компонентов, которые я использую в своем пользовательском компоненте.

export class MyTextField extends React.Component<MyProps, MyState> {
  private refTextField: React.RefObject<TextField>;
  constructor(props: MyProps) {
    super(props);
    this.refTextField = React.createRef();
  }

  render(): JSX.Element {
    const { id, label, value: defaultValue } = this.props;
    const { value } = this.state;
    const element = (
      <TextField ref={this.refTextField} id={id} label={label} defaultValue={defaultValue} value={value} />
    );

    return element;
  }
}

Во время компиляции я получаю сообщение об ошибке при объявлении моей ссылки:

'TextField' относится к значению, но здесь используется как тип. TS2749

Я попытался поместить "typeof TextField" в свое объявление, но у меня есть другое сообщение при оценке свойства ref в моем рендере:

Type 'RefObject < (props: TextFieldProps) => Element> 'не присваивается типу' ((instance: HTMLDivElement | null) => void) | RefObject | null | undefined '. Тип RefObject <(props: TextFieldProps) => Element> не может быть назначен типу RefObject. В типе '(props: TextFieldProps) => Element' отсутствуют следующие свойства из типа 'HTMLDivElement': align, addEventListener, removeEventListener, accessKey и еще 238. TS2322

Есть идеи? большое спасибо

Ответы [ 2 ]

3 голосов
/ 28 августа 2020

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

TL; DR в конце для фактического ответа на вопрос.

Когда вы создаете класс в TypeScript, имя этого класса относится как к типу экземпляра, так и к значению класса Javascript. Если вы ссылаетесь на этот класс как на тип, TypeScript автоматически определяет это как тип экземпляра этого класса. И если вы ссылаетесь на этот класс во время выполнения, он просто использует его, как в значении Javascript. И до сих пор все это хорошо и красиво.

class MyClass {}
let abc: MyClass; // ts recognizes as instance type
abc = new MyClass(); // completely fine, used here as the javascript value

Однако настоящая проблема заключается в том, когда вы экспортируете класс из модуля динамически . Когда вы каким-либо образом экспортируете класс, TypeScript может экспортировать только значение Javascript класса и не экспортирует тип. Поэтому, если вы импортируете его в другой модуль и попытаетесь сослаться на него как на тип, вы получите TS2749.

let intervariable = class MyClass{}
export const MyClass = intervariable; // TypeScript does not export type here.
import {MyClass} from './myclass';

let abc: MyClass; // TypeScript error TS2749

Когда это произойдет, особенно если это находится вне вашего контроля, мое решение получить тип экземпляра было просто использовать InstanceType и typeof:

import {MyClass} from './myclass';

let abc: InstanceType<typeof MyClass>; // no error
// the rest...

Оператор typeof возвращает вам тип конструктора класса для значения класса, а InstanceType generi c возвращает вам тип экземпляра, который вы хотите .

TL; DR: В вашем случае вам просто нужно написать InstanceType<typeof TextField> вместо TextField.

0 голосов
/ 28 мая 2020

попробуйте добавить тип к вашей функции createRef следующим образом:

 private refTextField: React.RefObject<TextField>;
  constructor(props: MyProps) {
    super(props);
    this.refTextField = React.createRef<React.RefObject<TextField>>(null);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...