В последнем посте мы узнали, как тип типов проверяет детей JSX в отношении реквизита конструктора. На этот раз мы углубимся в остальные реквизиты компонента и то, как они используются для Typechecking, которые действительны при создании JSX.
TypeScript обрабатывает внутренние, функциональные и классовые компоненты по -разному при выяснении, какие атрибуты могут быть назначены экспрессии JSX, построенной этими компонентами.
- Для конструкторов внутренних элементов (имя тега в нижнем случае) он смотрит на тип одного и того же имени свойства в
Jsx.intrinsicelements - Для конструкторов элементов функции он рассматривает тип первого параметра в сигнатуре вызова
- Для конструкторов элементов на основе классов он рассматривает тип свойства экземпляра, который имеет одинаковое имя под
Jsx.elementattributesproperty, и если этого не существует, он будет рассмотреть тип первого параметра в сигнатуре Constructor Call
Давайте подробно рассмотрим каждый случай:
Внутренние элементы конструкторы
Если ты JSX Пространство имен выглядит так:
interface HTMLAttributes{ children?: ReactNode className?: string id?: string onClick?(event: MouseEvent ): void ref?: { current?: T } } namespace JSX { interface IntrinsicElements { a: HTMLAttributes button: HTMLAttributes div: HTMLAttributes span: HTMLAttributes } }
затем Для элемента якоря доступные атрибуты вы можете дать тег эквивалентен Jsx.intrinsicelements ['a'] :
interface AnchorProps {
children?: ReactNode
className?: string
id?: string
onClick?(event: MouseEvent): void
ref?: { current?: HTMLAnchorElement }
}
declare const props: AnchorProps
const myAnchor =
Функциональные конструкторы
Если ваш компонент выглядит так:
interface Props {
onClick?(event: MouseEvent): void
disabled?: boolean
label: string
}
function MyButton(
props: Props & { children?: ReactNode },
some?: any,
other?: any,
parameters?: any
) {
return
}
Тогда доступные атрибуты Реквизит вместе с { дети?: ReactNode} , потому что это тип первого параметра в функции. Обратите внимание, что TypeScript также будет уважать необязательные и требуемые свойства и в типе реквизита:
const button =// error because label is marked as required in Props!
Конструкторы элементов класса
Если ваш класс выглядит так, и у вас есть JSX Пространство имен как это:
interface Props {
onClick?(event: MouseEvent): void
disabled?: boolean
label: string
}
class MyComponent {
_props: Props
constructor(props: Props & { children?: ReactNode }) {
this.props = props
}
render() {
return
}
}
namespace JSX {
interface ElementClass {
render(): any
}
interface ElementAttributesProperty {
_props: {}
}
}
Тогда доступные атрибуты для MyComponent являются Реквизит (Обратите внимание, что у этого не может быть дети ), потому что тип экземпляра MyComponent имеет собственность под названием _props , что такое же, как имя свойства внутри Jsx.elementattributesproperty . Если этот интерфейс в JSX Пространство имен не было там, вместо этого он посмотрел на тип первого параметра в конструкторе, который является Реквизит с { дети?: ReactNode} Анкет
Это охватывает все «внутренние» реквизиты, которые компонент может использовать внутри него. В React, однако, у нас есть концепция «внешнего» реквизита, которая является фактическим договором того, что вы можете передать в выражение JSX, построенное компонентом. Пример того, как внешние реквизиты отличаются от внутренних реквизитов, будет ref и ключ , а также DefaultProps :
refиключне доступны для использования в реализации компонента, ноключвсегда можно назначить любому выражению JSX в React иrefS может быть назначен любым классовым и внутренним выражениям JSX, а также Функциональные выражения с использованиемForwardRef.DefaultPropsПозволяет конкретной опоре к Всегда быть определенным внутри реализации компонента, но необязательно при назначении той же опоры в экспрессию JSX этого компонента.
В следующем посте мы узнаем, как TypeScript позволяет это произойти, используя больше JSX Магии пространства имен.
Оригинал: “https://dev.to/ferdaber/typescript-and-jsx-part-iii—typing-the-props-for-a-component-1pg2”