2017-01-06 2 views
5

Я пишу компонент более высокого порядка для моего проекта React, используя Typcript, который в основном является функцией, принимает компонент React как аргумент и возвращает новый компонент, который обтекает его.Аннотации типа для React Компонент более высокого порядка с использованием TypeScript

Тем не менее, как это работает, как ожидалось, TS жалуется, что «Возвращение типа экспортируемой функции имеет или использует личное имя„Анонимный класс“

функции в вопросе:.

export default function wrapperFunc <Props, State> (
    WrappedComponent: typeof React.Component, 
) { 
    return class extends React.Component<Props & State, {}> { 
     public render() { 
      return <WrappedComponent {...this.props} {...this.state} />; 
     } 
    }; 
} 

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

Пробная версия с явным указанием типа возврата typeof React.Component, как показано ниже, подавляет эту ошибку.

Функция в вопросе с явным возвращаемым типом:

export default function wrapperFunc <Props, State> (
    WrappedComponent: typeof React.Component, 
): typeof React.Component {      // <== Added this 
    return class extends React.Component<Props & State, {}> { 
     public render() { 
      return <WrappedComponent {...this.props} {...this.state} />; 
     } 
    }; 
} 

Однако, я не уверен, о справедливости такого подхода. Является ли это правильным подходом для решения этой конкретной ошибки в TypeScript? (Или я создаю непредвиденные побочные эффекты в другом месте? Или любой лучший способ сделать это?)

(Изменить) Изменить котировочный код в соответствии с предложением Даниила.

ответ

3

Type annotation for React Higher Order Component using TypeScript

Возвращения типа typeof React.Component правдив, но не очень полезно для пользователей, завернутой компоненты. Он отбрасывает информацию о том, какие реквизиты принимает компонент.

Резьбовые тиски обеспечивают удобный тип для этой цели, React.ComponentClass. Это тип класса, а не тип компонента, созданный из этого класса:

React.ComponentClass<Props> 

(Обратите внимание, что тип state не упоминается, как это внутренняя деталь).

В вашем случае:

export default function wrapperFunc <Props, State, CompState> (
    WrappedComponent: typeof React.Component, 
): React.ComponentClass<Props & State> { 
    return class extends React.Component<Props & State, CompState> { 
     public render() { 
      return <WrappedComponent {...this.props} {...this.state} />; 
     } 
    }; 
} 

Однако, вы делаете то же самое с параметром WrappedComponent. Исходя из того, как вы используете его внутри render, я предполагаю, что это также должно быть объявлено:

WrappedComponent: React.ComponentClass<Props & State>, 

Но это дикое предположение, как я предполагаю, что это не полная функция (CompState не используется, и Props & State также может быть параметром одного типа, который всегда появляется в этой комбинации).

+0

Благодарим Даниэля за подробный ответ. Я очистил код, но не смог очистить ненужную часть. Да, CompState не имеет отношения к этому вопросу. И я думаю, что ваша догадка правильна (по-настоящему оцените, что задумался). Я изменил вопрос, чтобы отказаться от части CompState, поскольку это может смутить других в будущем. – shuntksh

0

Более подходящий тип для входного параметра будет React.ComponentType, так как он также обрабатывает компоненты без гражданства.

type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P> 

Ниже приведен пример, поясняющий его использование.

import * as React from 'react'; 

export default function <P = {}>(
    WrappedComponent: React.ComponentType<P> 
): React.ComponentClass<P> { 
    return class extends React.Component<P> { 
    render() { 
     return <WrappedComponent {...this.props} />; 
    } 
    }; 
}