Редактировать: «Зачем использовать универсальный c тип?»
A)
Одна из причин заключается в возможности использовать предоставленный тип несколькими способами. Например, в официальном определении типа из React:
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Поскольку он определен с использованием обобщенного c, интерфейс FunctionComponent
"знает" следующие вещи о реализациях интерфейса:
- Тип первого аргумента функции
- Тип свойства
propTypes
stati c - Тип свойства
defaultProps
stati c
B)
Другая причина в том, что альтернатива довольно быстро запутывается. Возьмем следующее в качестве упрощенной версии интерфейса FunctionComponent
, реализованного без обобщений:
import React from 'react';
export interface FunctionComponentProps {
children: React.ReactNode;
}
export interface FunctionComponent {
(props: FunctionComponentProps, context?: any): React.ReactElement<any, any> | null;
}
Мы столкнемся с проблемами, когда захотим использовать этот тип:
export interface MyComponentProps extends FunctionComponentProps {
children: boolean; // invalid - can't change interface prop type
className: string;
}
export interface MyComponent extends FunctionComponent {
// invalid - same problem, cannot redeclare function signature
(props: MyComponentProps, context?: any): React.ReactElement<any, any> | null;
}
// inferred types of children and classNames is any because of the re-declarations
export const Button: MyComponent = ({ children, className }) => {
return <button className={className}>{children ? 'YES' : 'NO'}</button>;
};
Он «работает», если ваши пользовательские типы не расширяют предоставленный тип, но вы получите очень много бесполезного шаблонного кода, если заново изобретете колесо для каждого компонента.
export interface MyComponentProps {
children: boolean;
className: string;
}
export interface MyComponent {
(props: MyComponentProps, context?: any): React.ReactElement<any, any> | null;
}
export const Button: MyComponent = ({ children, className }) => {
return <button className={className}>{children ? 'YES' : 'NO'}</button>;
};
Оригинал Ответ
Синтаксис угловых скобок предоставляет дополнительную информацию системе проверки типов, поэтому преимущества предоставляются в виде улучшенной проверки типов.
Например:
Table.tsx
import React, { FunctionComponent } from "react";
export interface Props {
filtered: string[][];
}
const Table: FunctionComponent<Props> = ({ filtered }) => {
console.log("filtered = ", filtered);
// Type check fails because a ReactNode is not returned
//return <table />;
};
Table.defaultProps = {
// Type check fails because null is not a valid value for filtered
filtered: null
};
export default Table;
Table_bad.tsx
import React from "react";
export interface Props {
filtered: string[][];
}
const Table = ({ filtered }: Props) => {
console.log("filtered = ", filtered);
// Typescript does not know enough to complain that the render function does not return a ReactNode
//return <table />;
};
Table.defaultProps = {
// Typescript does not know that defaultProps should implement Props
filtered: null
};
export default Table;
Демо
https://codesandbox.io/s/so-61508203-56xum?file= / SRC / компоненты / Table_bad.tsx