Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Typescript, what is type PoorMansUnknown = {} | null | undefined and how would you deal with it?

Can someone please help me understand the meaning of the following type declaration...

type PoorMansUnknown = {} | null | undefined;

It is a TypeScript declaration and I have come across it in the context of the history package.

I have searched around to try and understand it myself but, given I'm quite new to TypeScript, it has me a bit stumped. I have found the following information on it:

  • original place I encountered it, history package
  • a stackoverflow question that relates to the same history package
  • another package using the approach
  • a twitter conversation on it which hints that it relates to 'sort of' declaring a type for something you're not to sure about...

My assumption is at this point, the author of this declaration intended it to be a way of saying... at runtime, this thing could be either an empty object or null or undefined.

For more context, the way this type turned up on my radar is within the package react-router-dom (typedef here). Specifically, I went to use the component Redirect and it's property to: object since I wanted to be able to tell the component I had routed to the location I was at previously

e.g.

<Redirect to={{
  pathname: "/login",
  state: { from: "current-path }
 }} />

The doco for react router says...

The state object can be accessed via this.props.location.state in the redirected-to component. This new referrer key (which is not a special name) would then be accessed via this.props.location.state.referrer in the Login component pointed to by the pathname '/login'

So, I go to access props.location.state as such...

const { from }  = location.state || { from: { path: '/' } }

and I get an error

Property 'from' does not exist on type '{} | { from: { path: string; }; }'.

I trace this through the typedef chain, starting with LocationState and make my way down to the declaration for PoorMansUnknown

This is where my confusion starts kicking in. What is this type? How should I deal with it?

I found something related to it here, which says to cast it as any. So I did that, as such:

const { from }  = location.state as any || { from: { path: '/' } }

But I'm not sure about that. It does work, but is it just a workaround?


Long story short, have you ever come across something like this before?

type PoorMansUnknown = {} | null | undefined;

and if so, what do you think it means and how would you work with components that make use of it?

like image 353
Danoz Avatar asked Mar 20 '20 05:03

Danoz


People also ask

What does undefined mean in typescript?

The value 'undefined' denotes that a variable has been declared, but hasn't been assigned any value. So, the value of the variable is 'undefined'.

What is null in typescript?

Null refers to a value that is either empty or doesn't exist. null means no value. To make a variable null we must assign null value to it as by default in typescript unassigned values are termed undefined. We can use typeof or '==' or '===' to check if a variable is null or undefined in typescript.

Is null or undefined typescript?

To check for null or undefined , compare the value to both null and undefined , e.g. if (name === undefined || name === null) {} . If either of the two conditions is met, the variable stores a null or undefined value and the if block will run.


1 Answers

PoorMansUnknown is supposed to be equivalent to the unknown type. We use PoorMansUnknown when unknown is not available, i.e. because we have to support an older version of TypeScript that does not support the unknown type.

"Unknown" is the default type of history state. You can customise it:

type Props = RouteComponentProps<{}, StaticContext, { from: { pathname: string; }; }>;

const MyComponent: FC<Props> = ({ location }) => {
  const { from }  = location.state || { from: { pathname: '/' } }
  // …
}

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ee646ad6a1cd47f71f099c0a03686d8f3547f3b0/types/react-router/test/examples-from-react-router-website/Auth.tsx#L72-L102

like image 50
Oliver Joseph Ash Avatar answered Sep 29 '22 23:09

Oliver Joseph Ash