history: switch default LocationState generic from any to unknown (#41580)

* Enable `strictNullChecks`

* Add test for generic state

* Replace `any` with `PoorMansUnknown`

* Define state generics
This commit is contained in:
Oliver Joseph Ash
2020-01-14 17:28:29 +00:00
committed by John Reilly
parent f4f29cb4f9
commit 1f36fb3afd
5 changed files with 24 additions and 6 deletions
+10 -1
View File
@@ -9,6 +9,8 @@ let input = { value: "" };
{
let history = createBrowserHistory<{ some: 'state' }>();
history.location.state; // $ExpectType { some: "state"; }
// Listen for changes to the current location. The
// listener is called once immediately.
let unlisten = history.listen(function (location) {
@@ -114,7 +116,8 @@ let input = { value: "" };
}
{
let eventTarget: EventTarget;
const anything: any = {};
const eventTarget: EventTarget = anything;
DOMUtils.addEventListener(eventTarget, 'onload', function (event) { event.preventDefault(); });
DOMUtils.removeEventListener(eventTarget, 'onload', function (event) { event.preventDefault(); });
DOMUtils.getConfirmation('confirm?', (result) => console.log(result));
@@ -125,3 +128,9 @@ let input = { value: "" };
let supportsDOM = ExecutionEnvironment.canUseDOM;
let isExtraneousPopstateEvent = DOMUtils.isExtraneousPopstateEvent;
}
{
const anything: any = {};
const history: History = anything;
history.location.state; // $ExpectType PoorMansUnknown
}
+4 -1
View File
@@ -49,7 +49,10 @@ export namespace History {
location: Location<S>,
action: Action,
) => void;
export type LocationState = any;
// The value type here is a "poor man's `unknown`". When these types support TypeScript
// 3.0+, we can replace this with `unknown`.
type PoorMansUnknown = {} | null | undefined;
export type LocationState = PoorMansUnknown;
export type Path = string;
export type Pathname = string;
export type Search = string;
+1 -1
View File
@@ -7,7 +7,7 @@
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": false,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
@@ -8,6 +8,7 @@ import {
Redirect,
withRouter
} from 'react-router-dom';
import { StaticContext } from 'react-router';
////////////////////////////////////////////////////////////
// 1. Click the public page
@@ -68,7 +69,9 @@ const PrivateRoute: React.SFC<RouteProps> = ({ component, ...rest }) => (
const Public: React.SFC<RouteComponentProps> = () => <h3>Public</h3>;
const Protected: React.SFC<RouteComponentProps> = () => <h3>Protected</h3>;
class Login extends React.Component<RouteComponentProps, {redirectToReferrer: boolean}> {
type Props = RouteComponentProps<{}, StaticContext, { from: { pathname: string; }; }>;
class Login extends React.Component<Props, {redirectToReferrer: boolean}> {
state = {
redirectToReferrer: false
};
@@ -6,6 +6,7 @@ import {
Route,
Link
} from 'react-router-dom';
import { StaticContext } from 'react-router';
// This example shows how to render two different screens
// (or the same screen in a different context) at the same url,
@@ -16,7 +17,9 @@ import {
// are the same as before but now we see them inside a modal
// on top of the old screen.
class ModalSwitch extends React.Component<RouteComponentProps> {
type Props = RouteComponentProps<{}, StaticContext, { modal: boolean }>;
class ModalSwitch extends React.Component<Props> {
// We can pass a location to <Switch/> that will tell it to
// ignore the router's current location and use the location
// prop instead.
@@ -31,7 +34,7 @@ class ModalSwitch extends React.Component<RouteComponentProps> {
// is still `/` even though its `/images/2`.
previousLocation = this.props.location;
componentWillUpdate(nextProps: RouteComponentProps) {
componentWillUpdate(nextProps: Props) {
const { location } = this.props;
// set previousLocation if props.location is not modal
if (