Allow specifying void for component state type parameter. (#8673)

* Allow specifying `void` for component state type parameter.

Per comments on https://github.com/DefinitelyTyped/DefinitelyTyped/pull/8543,
the type parameter for component state was changed to `{}` from `any` for
increased type safety, but prevents specifying (non-functional) stateless
components without having empty state parameters, which seems messy. This
changes the type to `{} | void` to allow this while staying stricter than
`any`.

* Make react tests a bit more strict.

* Rename State -> ComponentState to make it a bit more explicit.
This commit is contained in:
Sean Kelley
2016-04-12 08:40:40 -07:00
committed by Masahiro Wakame
parent 151dc309c9
commit b9642fb8ac
3 changed files with 29 additions and 22 deletions

View File

@@ -18,14 +18,14 @@ declare namespace __React {
element: SFCElement<P>,
container: Element,
callback?: () => any): void;
function render<P, T extends Component<P, {}>>(
function render<P, T extends Component<P, ComponentState>>(
element: CElement<P, T>,
container: Element,
callback?: (component: T) => any): T;
function render<P>(
element: ReactElement<P>,
container: Element,
callback?: (component?: Component<P, {}> | Element) => any): Component<P, {}> | Element | void;
callback?: (component?: Component<P, ComponentState> | Element) => any): Component<P, ComponentState> | Element | void;
function unmountComponentAtNode(container: Element): boolean;
@@ -40,7 +40,7 @@ declare namespace __React {
element: DOMElement<P, T>,
container: Element,
callback?: (element: T) => any): T;
function unstable_renderSubtreeIntoContainer<P, T extends Component<P, {}>>(
function unstable_renderSubtreeIntoContainer<P, T extends Component<P, ComponentState>>(
parentComponent: Component<any, any>,
element: CElement<P, T>,
container: Element,
@@ -54,7 +54,7 @@ declare namespace __React {
parentComponent: Component<any, any>,
element: ReactElement<P>,
container: Element,
callback?: (component?: Component<P, {}> | Element) => any): Component<P, {}> | Element | void;
callback?: (component?: Component<P, ComponentState> | Element) => any): Component<P, ComponentState> | Element | void;
}
namespace __DOMServer {

View File

@@ -138,6 +138,8 @@ class ModernComponent extends React.Component<Props, State>
}
}
class ModernComponentNoState extends React.Component<Props, void> {}
interface SCProps {
foo?: number;
}
@@ -182,6 +184,8 @@ var domFactoryElement: React.DOMElement<React.DOMAttributes, Element> =
// React.createElement
var element: React.CElement<Props, ModernComponent> =
React.createElement(ModernComponent, props);
var elementNoState: React.CElement<Props, ModernComponentNoState> =
React.createElement(ModernComponentNoState, props);
var statelessElement: React.SFCElement<SCProps> =
React.createElement(StatelessComponent, props);
var classicElement: React.ClassicElement<Props> =
@@ -216,6 +220,8 @@ var clonedDOMElement: React.ReactHTMLElement<HTMLDivElement> =
// React.render
var component: ModernComponent =
ReactDOM.render(element, container);
var componentNoState: ModernComponentNoState =
ReactDOM.render(elementNoState, container);
var classicComponent: React.ClassicComponent<Props, any> =
ReactDOM.render(classicElement, container);
var domComponent: Element =

37
react/react.d.ts vendored
View File

@@ -13,6 +13,7 @@ declare namespace __React {
type Key = string | number;
type Ref<T> = string | ((instance: T) => any);
type ComponentState = {} | void;
interface Attributes {
key?: Key;
@@ -31,13 +32,13 @@ declare namespace __React {
type: SFC<P>;
}
type CElement<P, T extends Component<P, {}>> = ComponentElement<P, T>;
interface ComponentElement<P, T extends Component<P, {}>> extends ReactElement<P> {
type CElement<P, T extends Component<P, ComponentState>> = ComponentElement<P, T>;
interface ComponentElement<P, T extends Component<P, ComponentState>> extends ReactElement<P> {
type: ComponentClass<P>;
ref?: Ref<T>;
}
type ClassicElement<P> = CElement<P, ClassicComponent<P, {}>>;
type ClassicElement<P> = CElement<P, ClassicComponent<P, ComponentState>>;
interface DOMElement<P extends DOMAttributes, T extends Element> extends ReactElement<P> {
type: string;
@@ -62,12 +63,12 @@ declare namespace __React {
(props?: P & Attributes, ...children: ReactNode[]): SFCElement<P>;
}
interface ComponentFactory<P, T extends Component<P, {}>> {
interface ComponentFactory<P, T extends Component<P, ComponentState>> {
(props?: P & ClassAttributes<T>, ...children: ReactNode[]): CElement<P, T>;
}
type CFactory<P, T extends Component<P, {}>> = ComponentFactory<P, T>;
type ClassicFactory<P> = CFactory<P, ClassicComponent<P, {}>>;
type CFactory<P, T extends Component<P, ComponentState>> = ComponentFactory<P, T>;
type ClassicFactory<P> = CFactory<P, ClassicComponent<P, ComponentState>>;
interface DOMFactory<P extends DOMAttributes, T extends Element> {
(props?: P & ClassAttributes<T>, ...children: ReactNode[]): DOMElement<P, T>;
@@ -101,8 +102,8 @@ declare namespace __React {
type: string): DOMFactory<P, T>;
function createFactory<P>(type: SFC<P>): SFCFactory<P>;
function createFactory<P>(
type: ClassType<P, ClassicComponent<P, {}>, ClassicComponentClass<P>>): CFactory<P, ClassicComponent<P, {}>>;
function createFactory<P, T extends Component<P, {}>, C extends ComponentClass<P>>(
type: ClassType<P, ClassicComponent<P, ComponentState>, ClassicComponentClass<P>>): CFactory<P, ClassicComponent<P, ComponentState>>;
function createFactory<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>>(
type: ClassType<P, T, C>): CFactory<P, T>;
function createFactory<P>(type: ComponentClass<P> | SFC<P>): Factory<P>;
@@ -115,10 +116,10 @@ declare namespace __React {
props?: P & Attributes,
...children: ReactNode[]): SFCElement<P>;
function createElement<P>(
type: ClassType<P, ClassicComponent<P, {}>, ClassicComponentClass<P>>,
props?: P & ClassAttributes<ClassicComponent<P, {}>>,
...children: ReactNode[]): CElement<P, ClassicComponent<P, {}>>;
function createElement<P, T extends Component<P, {}>, C extends ComponentClass<P>>(
type: ClassType<P, ClassicComponent<P, ComponentState>, ClassicComponentClass<P>>,
props?: P & ClassAttributes<ClassicComponent<P, ComponentState>>,
...children: ReactNode[]): CElement<P, ClassicComponent<P, ComponentState>>;
function createElement<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>>(
type: ClassType<P, T, C>,
props?: P & ClassAttributes<T>,
...children: ReactNode[]): CElement<P, T>;
@@ -135,7 +136,7 @@ declare namespace __React {
element: SFCElement<P>,
props?: Q, // should be Q & Attributes, but then Q is inferred as {}
...children: ReactNode[]): SFCElement<P>;
function cloneElement<P extends Q, Q, T extends Component<P, {}>>(
function cloneElement<P extends Q, Q, T extends Component<P, ComponentState>>(
element: CElement<P, T>,
props?: Q, // should be Q & ClassAttributes<T>
...children: ReactNode[]): CElement<P, T>;
@@ -201,7 +202,7 @@ declare namespace __React {
}
interface ComponentClass<P> {
new(props?: P, context?: any): Component<P, {}>;
new(props?: P, context?: any): Component<P, ComponentState>;
propTypes?: ValidationMap<P>;
contextTypes?: ValidationMap<any>;
childContextTypes?: ValidationMap<any>;
@@ -210,7 +211,7 @@ declare namespace __React {
}
interface ClassicComponentClass<P> extends ComponentClass<P> {
new(props?: P, context?: any): ClassicComponent<P, {}>;
new(props?: P, context?: any): ClassicComponent<P, ComponentState>;
getDefaultProps?(): P;
}
@@ -219,7 +220,7 @@ declare namespace __React {
* a single argument, which is useful for many top-level API defs.
* See https://github.com/Microsoft/TypeScript/issues/7234 for more info.
*/
type ClassType<P, T extends Component<P, {}>, C extends ComponentClass<P>> =
type ClassType<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>> =
C &
(new() => T) &
(new() => { props: P });
@@ -1180,7 +1181,7 @@ declare namespace __React {
lineClamp?: number;
/**
* Specifies the height of an inline block level element.
* Specifies the height of an inline block level element.
*/
lineHeight?: number | string;
@@ -2033,7 +2034,7 @@ declare namespace __React {
results?: number;
security?: string;
unselectable?: boolean;
// Allows aria- and data- Attributes
[key: string]: any;
}