-
Notifications
You must be signed in to change notification settings - Fork 30.5k
Add more of the new features added in React 16.6 #30054
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8108d36
3519670
9ea5462
5fdb7dc
66909c0
5a081ad
a6b4dc7
d066793
fa0a57d
c47014e
055cc6d
25c2862
88991b0
67a704f
4c49d3a
0a10ba0
bab3ed0
299c1f2
2b9cb56
02fdb38
3a26c43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -191,19 +191,19 @@ declare namespace React { | |||||
| ...children: ReactNode[]): DOMElement<P, T>; | ||||||
|
|
||||||
| // Custom components | ||||||
| function createElement<P>( | ||||||
| function createElement<P extends {}>( | ||||||
| type: SFC<P>, | ||||||
| props?: Attributes & P | null, | ||||||
| ...children: ReactNode[]): SFCElement<P>; | ||||||
| function createElement<P>( | ||||||
| function createElement<P extends {}>( | ||||||
| type: ClassType<P, ClassicComponent<P, ComponentState>, ClassicComponentClass<P>>, | ||||||
| props?: ClassAttributes<ClassicComponent<P, ComponentState>> & P | null, | ||||||
| ...children: ReactNode[]): CElement<P, ClassicComponent<P, ComponentState>>; | ||||||
| function createElement<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>>( | ||||||
| function createElement<P extends {}, T extends Component<P, ComponentState>, C extends ComponentClass<P>>( | ||||||
| type: ClassType<P, T, C>, | ||||||
| props?: ClassAttributes<T> & P | null, | ||||||
| ...children: ReactNode[]): CElement<P, T>; | ||||||
| function createElement<P>( | ||||||
| function createElement<P extends {}>( | ||||||
| type: SFC<P> | ComponentClass<P> | string, | ||||||
| props?: Attributes & P | null, | ||||||
| ...children: ReactNode[]): ReactElement<P>; | ||||||
|
|
@@ -255,11 +255,40 @@ declare namespace React { | |||||
| unstable_observedBits?: number; | ||||||
| } | ||||||
|
|
||||||
| type Provider<T> = ComponentType<ProviderProps<T>>; | ||||||
| type Consumer<T> = ComponentType<ConsumerProps<T>>; | ||||||
| // TODO: similar to how Fragment is actually a symbol, the values returned from createContext, | ||||||
| // forwardRef and memo are actually objects that are treated specially by the renderer; see: | ||||||
| // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/ReactContext.js#L35-L48 | ||||||
| // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/forwardRef.js#L42-L45 | ||||||
| // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/memo.js#L27-L31 | ||||||
| // However, we have no way of telling the JSX parser that it's a JSX element type or its props other than | ||||||
| // by pretending to be a normal component. | ||||||
| // | ||||||
| // We don't just use ComponentType or SFC types because you are not supposed to attach statics to this | ||||||
| // object, but rather to the original function. | ||||||
| interface ExoticComponent<P = {}> { | ||||||
| /** | ||||||
| * **NOTE**: Exotic components are not callable. | ||||||
| */ | ||||||
| (props: P): (ReactElement<any>|null); | ||||||
| readonly $$typeof: symbol; | ||||||
| } | ||||||
|
|
||||||
| interface NamedExoticComponent<P = {}> extends ExoticComponent<P> { | ||||||
| displayName?: string; | ||||||
| } | ||||||
|
|
||||||
| interface ProviderExoticComponent<P> extends ExoticComponent<P> { | ||||||
| propTypes?: ValidationMap<P>; | ||||||
| } | ||||||
|
|
||||||
| // NOTE: only the Context object itself can get a displayName | ||||||
| // https://github.com/facebook/react-devtools/blob/e0b854e4c/backend/attachRendererFiber.js#L310-L325 | ||||||
| type Provider<T> = ProviderExoticComponent<ProviderProps<T>>; | ||||||
| type Consumer<T> = ExoticComponent<ConsumerProps<T>>; | ||||||
| interface Context<T> { | ||||||
| Provider: Provider<T>; | ||||||
| Consumer: Consumer<T>; | ||||||
| displayName?: string; | ||||||
| } | ||||||
| function createContext<T>( | ||||||
| defaultValue: T, | ||||||
|
|
@@ -269,8 +298,25 @@ declare namespace React { | |||||
| function isValidElement<P>(object: {} | null | undefined): object is ReactElement<P>; | ||||||
|
|
||||||
| const Children: ReactChildren; | ||||||
| const Fragment: ComponentType; | ||||||
| const StrictMode: ComponentType; | ||||||
| const Fragment: ExoticComponent<{ children?: ReactNode }>; | ||||||
| const StrictMode: ExoticComponent<{ children?: ReactNode }>; | ||||||
| /** | ||||||
| * This feature is not yet available for server-side rendering. | ||||||
| * Suspense support will be added in a later release. | ||||||
| */ | ||||||
| const Suspense: ExoticComponent<{ | ||||||
| children?: ReactNode | ||||||
|
|
||||||
| /** A fallback react tree to show when a Suspense child (like React.lazy) suspends */ | ||||||
| fallback: NonNullable<ReactNode>|null | ||||||
|
|
||||||
| // I tried looking at the code but I have no idea what it does. | ||||||
| // https://github.com/facebook/react/issues/13206#issuecomment-432489986 | ||||||
| /** | ||||||
| * Not implemented yet, requires unstable_ConcurrentMode | ||||||
| */ | ||||||
| // maxDuration?: number | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know whether to leave this in or not. The code to support it technically exists, but is unreachable without |
||||||
| }>; | ||||||
| const version: string; | ||||||
|
|
||||||
| // | ||||||
|
|
@@ -283,6 +329,29 @@ declare namespace React { | |||||
| // tslint:disable-next-line:no-empty-interface | ||||||
| interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { } | ||||||
| class Component<P, S> { | ||||||
| // tslint won't let me format the sample code in a way that vscode likes it :( | ||||||
| /** | ||||||
| * If set, `this.context` will be set at runtime to the current value of the given Context. | ||||||
| * | ||||||
| * Usage: | ||||||
| * | ||||||
| * ```ts | ||||||
| * type MyContext = number | ||||||
| * const Ctx = React.createContext<MyContext>(0) | ||||||
| * | ||||||
| * class Foo extends React.Component { | ||||||
| * static contextType = Ctx | ||||||
| * context!: MyContext | ||||||
| * render () { | ||||||
| * return <>My context's value: {this.context}</>; | ||||||
| * } | ||||||
| * } | ||||||
| * ``` | ||||||
| * | ||||||
| * @see https://reactjs.org/docs/context.html#classcontexttype | ||||||
| */ | ||||||
| static contextType?: Context<any>; | ||||||
|
|
||||||
| constructor(props: Readonly<P>); | ||||||
| /** | ||||||
| * @deprecated | ||||||
|
|
@@ -308,11 +377,6 @@ declare namespace React { | |||||
| // on the existence of `children` in `P`, then we should remove this. | ||||||
| readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>; | ||||||
| state: Readonly<S>; | ||||||
| /** | ||||||
| * @deprecated | ||||||
| * https://reactjs.org/docs/legacy-context.html | ||||||
| */ | ||||||
| context: any; | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed this to make sure there's no magic
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, it is strange, cause here https://reactjs.org/docs/context.html#classcontexttype we can see, React allows us to use just this.context, but it is not possible, if context will be deleted from types of Component.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By the way, there is no anything like value in Component.contextType.Provider.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The point is to force the user to declare it themselves because there is nothing better we can do other than
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, could you explain, why this code is not working: Type of context is any always( But it works perfectly in my own component.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is because, by declaring it in the superclass, you don't have access to its type as assigned in the subclass. The type of the constructor itself is not generic so it just uses the type as declared, assuming This is the deficiency in TypeScript's class declaration language: it is possible to make an instance type generic, but not the constructor object itself generic. There is a possible hack with constructible interfaces, though, if they're even accepted in an
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for explanation. I agree, what it is ok to get rid of context from typings. |
||||||
| /** | ||||||
| * @deprecated | ||||||
| * https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs | ||||||
|
|
@@ -417,6 +481,7 @@ declare namespace React { | |||||
| // Unfortunately, we have no way of declaring that the component constructor must implement this | ||||||
| interface StaticLifecycle<P, S> { | ||||||
| getDerivedStateFromProps?: GetDerivedStateFromProps<P, S>; | ||||||
| getDerivedStateFromError?: GetDerivedStateFromError<P, S>; | ||||||
| } | ||||||
|
|
||||||
| type GetDerivedStateFromProps<P, S> = | ||||||
|
|
@@ -427,6 +492,15 @@ declare namespace React { | |||||
| */ | ||||||
| (nextProps: Readonly<P>, prevState: S) => Partial<S> | null; | ||||||
|
|
||||||
| type GetDerivedStateFromError<P, S> = | ||||||
| /** | ||||||
| * This lifecycle is invoked after an error has been thrown by a descendant component. | ||||||
| * It receives the error that was thrown as a parameter and should return a value to update state. | ||||||
| * | ||||||
| * Note: its presence prevents any of the deprecated lifecycle methods from being invoked | ||||||
| */ | ||||||
| (error: any) => Partial<S> | null; | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually don't know if this is allowed to return
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the argument be of type
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept it the same type as try {
...
} catch (e) {
// e will _always_ be `any`
// giving it another type is a build error
}You can also throw anything in javascript; even |
||||||
|
|
||||||
| // This should be "infer SS" but can't use it yet | ||||||
| interface NewLifecycle<P, S, SS> { | ||||||
| /** | ||||||
|
|
@@ -558,7 +632,45 @@ declare namespace React { | |||||
|
|
||||||
| function createRef<T>(): RefObject<T>; | ||||||
|
|
||||||
| function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ComponentType<P & ClassAttributes<T>>; | ||||||
| // will show `ForwardRef(${Component.displayName || Component.name})` in devtools by default, | ||||||
| // but can be given its own specific name | ||||||
| interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> { | ||||||
| defaultProps?: Partial<P>; | ||||||
| } | ||||||
|
|
||||||
| function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<P & ClassAttributes<T>>; | ||||||
|
|
||||||
| type ComponentProps<T extends ComponentType<any>> = | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need DefinitelyTyped/types/react/index.d.ts Line 53 in 549360d
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, if there is no argument it'll be inferred as It's the problem of |
||||||
| T extends ComponentType<infer P> ? P : {}; | ||||||
| type ComponentPropsWithRef<T extends ComponentType<any>> = | ||||||
| T extends ComponentClass<infer P> | ||||||
| ? P & ClassAttributes<InstanceType<T>> | ||||||
| : T extends SFC<infer P> | ||||||
| ? P | ||||||
| : {}; | ||||||
|
|
||||||
| // will show `Memo(${Component.displayName || Component.name})` in devtools by default, | ||||||
| // but can be given its own specific name | ||||||
| interface MemoExoticComponent<T extends ComponentType<any>> extends NamedExoticComponent<ComponentPropsWithRef<T>> { | ||||||
| readonly type: T; | ||||||
| } | ||||||
|
|
||||||
| function memo<P extends object>( | ||||||
| Component: SFC<P>, | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this right? If I have a render prop component (where children might be a function), it's not being inferred as functional component.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implicit Again 🙄 I guess I have a New Years break project for a breaking change. Hopefully one I can get to compile. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm investigating it further. The problem may not be
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sandersn @johnnyreilly Would it be possible to condition this breaking change on a specific TypeScript version through typesVersion? I was thinking of being able to make the change incremental by only updating types on demand, when people update to, say, TS3.3. This would require kind of a "max supported TS version" on types that depend on I'm a bit afraid of it being a python3 problem, though, but the technical debt of Yes, I could work around this problem in this specific instance by changing the input to a function instead of FunctionComponent, but it's pervasive and everywhere. A lot of things that currently work in the ecosystem (like function children) work because of ossified bugs in the types, not because of features.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @diegohaz ah, yes, that is the one big problem with mapped types and infer (and the lack of kinds?); they erase generics and collapse unions. If the props are either of those the output type may be funky.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In another thread we decided it was time to update the types to expect TS 3
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm afraid I haven't played with |
||||||
| propsAreEqual?: (prevProps: Readonly<P & { children?: ReactNode }>, nextProps: Readonly<P & { children?: ReactNode }>) => boolean | ||||||
| ): NamedExoticComponent<P>; | ||||||
| function memo<T extends ComponentType<any>>( | ||||||
| Component: T, | ||||||
| propsAreEqual?: (prevProps: Readonly<ComponentProps<T>>, nextProps: Readonly<ComponentProps<T>>) => boolean | ||||||
| ): MemoExoticComponent<T>; | ||||||
|
|
||||||
| interface LazyExoticComponent<T extends ComponentType<any>> extends ExoticComponent<ComponentPropsWithRef<T>> { | ||||||
| readonly _result: T; | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not really happy about this. Having an underscored value here looks like reaching into internals; but it's the only way to have access to An alternative is to make up our own fictional prop name. |
||||||
| } | ||||||
|
|
||||||
| function lazy<T extends ComponentType<any>>( | ||||||
| factory: () => Promise<{ default: T }> | ||||||
| ): LazyExoticComponent<T>; | ||||||
|
|
||||||
| // | ||||||
| // React Hooks | ||||||
|
|
@@ -2460,6 +2572,14 @@ type Defaultize<P, D> = P extends any | |||||
| & Partial<Pick<D, Exclude<keyof D, keyof P>>> | ||||||
| : never; | ||||||
|
|
||||||
| type ReactManagedAttributes<C, P> = C extends { propTypes: infer T; defaultProps: infer D; } | ||||||
| ? Defaultize<MergePropTypes<P, PropTypes.InferProps<T>>, D> | ||||||
| : C extends { propTypes: infer T; } | ||||||
| ? MergePropTypes<P, PropTypes.InferProps<T>> | ||||||
| : C extends { defaultProps: infer D; } | ||||||
| ? Defaultize<P, D> | ||||||
| : P; | ||||||
|
|
||||||
| declare global { | ||||||
| namespace JSX { | ||||||
| // tslint:disable-next-line:no-empty-interface | ||||||
|
|
@@ -2470,13 +2590,13 @@ declare global { | |||||
| interface ElementAttributesProperty { props: {}; } | ||||||
| interface ElementChildrenAttribute { children: {}; } | ||||||
|
|
||||||
| type LibraryManagedAttributes<C, P> = C extends { propTypes: infer T; defaultProps: infer D; } | ||||||
| ? Defaultize<MergePropTypes<P, PropTypes.InferProps<T>>, D> | ||||||
| : C extends { propTypes: infer T; } | ||||||
| ? MergePropTypes<P, PropTypes.InferProps<T>> | ||||||
| : C extends { defaultProps: infer D; } | ||||||
| ? Defaultize<P, D> | ||||||
| : P; | ||||||
| // We can't recurse forever because `type` can't be self-referential; | ||||||
| // let's assume it's reasonable to do a single React.lazy() around a single React.memo() / vice-versa | ||||||
| type LibraryManagedAttributes<C, P> = C extends React.MemoExoticComponent<infer T> | React.LazyExoticComponent<infer T> | ||||||
| ? T extends React.MemoExoticComponent<infer U> | React.LazyExoticComponent<infer U> | ||||||
| ? ReactManagedAttributes<U, P> | ||||||
| : ReactManagedAttributes<T, P> | ||||||
| : ReactManagedAttributes<C, P>; | ||||||
|
|
||||||
| // tslint:disable-next-line:no-empty-interface | ||||||
| interface IntrinsicAttributes extends React.Attributes { } | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
React will throw at runtime if the Suspense suspends and the fallback is
undefined, butnullis ok.