Definitelytyped: Property 'from' does not exist on type '{}'

Created on 17 Jan 2020  路  22Comments  路  Source: DefinitelyTyped/DefinitelyTyped

I now get compilation errors in a project where i use react-router-dom. react-router-dom is using createBrowserHistory() and I'm accessing location.state in my code.

Can I prevent the TypeScript compiler from caring about this?

Error introduced by the following change:

41580

  • [x] I tried using the @types/xxxx package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @sergey-buturlakin, @ngbrown, @rokoroku, @danielnixon

If you do not mention the authors the issue will be ignored.

(edit: grammar)

Most helpful comment

If you want to get around this in not a type safe way and only if you are sure you are getting the values, try this.

const { valueX, valueY } = location.state as any

All 22 comments

I should mention that the workaround is to do npm install @types/[email protected] --save-dev for anyone ending up here.

If you don't care about type checking history location state, you can opt out by casting it to any?

Any way to describe the expected shape of the state like is done for the params?

e.g.:

interface Props extends RouteComponentProps<{
  myParamProp?: string;
}> {
  myNormalProp: boolean;
}

Any way describe the expected shape of the state like is done for the params?

@adambowles: yep. Both History and Location have a single type param, so wherever you have one of those (either as a member of your own type or as a function parameter) replace them with History<MyHistoryStateType> or Location<MyHistoryStateType>.

@danielnixon Thanks

FYI for anyone else landing here I implemented location state shape like this:

interface Props extends RouteComponentProps<
  { myParamProp?: string }, // this.props.match.params.myParamProp
  any, // history
  { myStateProp?: string }, // this.props.location.state.myStateProp
> {
  myNormalProp: boolean;
}

If you don't care about type checking history location state, you can opt out by casting it to any?

Of course. Thanks.

Changing
const { from } = self.props.location.state || { from: { pathname: "/" }};
to
const { from } = self.props.location.state as any || { from: { pathname: "/" }};
works (obviously, why did I not think of this...?) with version 4.7.4.

I don't like having to explicitly cast location.stateto any so we reverted to version 4.7.3.

Edit: phrasing

I don't like to loose the type checking so we reverted to version 4.7.3.

But the state type param defaults to any in 4.7.3, so you're no safer unless you specify that type param. this applies equally to 4.7.3 without the cast to any and 4.7.4 with the cast to any.

I don't like to loose the type checking so we reverted to version 4.7.3.

But the state type param defaults to any in 4.7.3, so you're no safer unless you specify that type param. this applies equally to 4.7.3 without the cast to any and 4.7.4 with the cast to any.

Yes, sure. My phrasing was a bit off. I don't like to explicitly casting this to any, especially when I'm not the one using the method that should supply the generic type param. Does that make sense?

I can't add proper types any more

<Prompt
    when={dirty}
    message={(location: Location<{ forced?: boolean }>) => location.state?.forced || "Are you sure you want to leave?"}
// `Type 'Location<PoorMansUnknown>' is not assignable to type 'Location<{ forced?: boolean | undefined; }>'.`
/>

@evertbouw this PR should help: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/41730

Once that PR lands, you can replace <Prompt with <Prompt<{ forced?: boolean }>.

This issue is unlikely to be fixed (see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/41675#pullrequestreview-346777995) so shall we just close it?

Can we close this issue now? This is not a bug, and this thread + the linked StackOverflow issues provide solutions.

This has broken my usage of createPath too (see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/history/PathUtils.d.ts#L9 ) because createPath is missing the generic type param.

@johnnyreilly please reconsider merging https://github.com/DefinitelyTyped/DefinitelyTyped/pull/41675

See also this comment, where the number of thumbs up imply support for reverting this change.

I cannot use props.location.state at all as it complains any type I add doesn't exist on PoorMansUnknown. Does anyone have an example?

<NavLink
  to={{
    pathname: '/testing',
    state: {
      id: 'foobar/123',
    },
  }}
>
...
<Route
  path='foobar/:id',
  render={(props) => {
    const { id } = props.location.state // this is an error
    ...
>

I've tried things like <NavLink<SomeExtendedType> etc and nothing works.

Hi there, just joining in the discussion in relation to this. Hoping that's ok?

I've asked a question on StackOverflow in relation to this use of PoorMansUnknown, but I just realised the question was probably more suited to being posted here directly...

If anyone has any thoughts on it... just trying to learn as I go at the moment and this one has me a bit stumped.

Thanks,
Dan

@danielnixon

createPath is missing the generic type param.

Can you elaborate on what the problem is you're facing and how it's related to this change?

Side note: it looks like createPath misuses generics. It should be re-written as:

export function createPath(location: LocationDescriptorObject<any>): Path;
Terms

Reasoning: the generic is only used by one param and is not used by the return type. See:


@tsujp There are examples in the tests: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ee646ad6a1cd47f71f099c0a03686d8f3547f3b0/types/react-router/test/examples-from-react-router-website/Auth.tsx#L72-L102


@miller-productions I answered on StackOverflow. 馃槃 Hope that helps!

If you want to get around this in not a type safe way and only if you are sure you are getting the values, try this.

const { valueX, valueY } = location.state as any
Was this page helpful?
0 / 5 - 0 ratings

Related issues

JudeAlquiza picture JudeAlquiza  路  3Comments

ArtemZag picture ArtemZag  路  3Comments

fasatrix picture fasatrix  路  3Comments

csharpner picture csharpner  路  3Comments

jgoz picture jgoz  路  3Comments