Skip to content
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

Null is not treated as Object in component prop check #1961

Closed
fnlctrl opened this issue Dec 4, 2015 · 12 comments
Closed

Null is not treated as Object in component prop check #1961

fnlctrl opened this issue Dec 4, 2015 · 12 comments

Comments

@fnlctrl
Copy link
Member

fnlctrl commented Dec 4, 2015

I have a component that let's user select an object from an array.

<comp :selected.sync="selectedObject">
// parent data
data: {
    selectedObject: null
}
// comp prop
props: {
    selected: {twoWay: true, type: Object}
}

and in parent template I have something like

<div v-if="selectedObject"> blah blah blah </div>
<div v-else> please select an object </div>

which displays different content based on whether an object is selected.

and I get

[Vue warn]: Invalid prop: type check failed for selected="selectedObject". Expected Object, got Null.

I know i can just remove the "type: Object" check and suppress the warning,
but wouldn't it be better if component props checks treat null as an object?

Because javascript does that (typeof null === 'object'),
and setting null as an initial value (to my knowledge) doesn't affect mutation observation.

@yyx990803
Copy link
Member

It fails because null is not an Object... the typeof behavior is commonly considered a bad design in the JavaScript language itself.

Just initialize it to an empty object.

@fnlctrl
Copy link
Member Author

fnlctrl commented Dec 4, 2015

Initializing with an {} will cause it to evaluate to true.. which means I won't be able to use v-if="selectedObject" and I'll have to create another variable to store whether an object is selected.
I'll just remove the type check then..

@lsbyerley
Copy link

@fnlctrl you just need to change it to v-if="Object.keys(selectedObj).length > 0"

@dulowski-marek
Copy link

dulowski-marek commented May 29, 2018

@fnlctrl Which is a workaround, where either using such an exaggerated expression in template or writing a getter for each object to check if it is initialized seems not right.

Using Typescript with Vue complicates this even more, as one has to denote all objects as Partial<T> or T | {} for this approach to work.

What is the status of this issue in upcoming 3.0 release?

@christhofer
Copy link

christhofer commented Jan 23, 2019

So, this any type in documentation is not actually any type?
image

posva added a commit to posva/vue that referenced this issue Jan 23, 2019
Based on vuejs#1961. It wasn't possible to specify a required prop of type object and pass null as the
value
@Flamenco
Copy link

When using Typescript, I have no way to specify string | null.

My use-case is a filter that sets the value to null when cleared.
I know the workaround is to transform the null value to a string
before sending the prop to the component, but I should not have to do that.

Ideally, one of these would be the syntax:

{type: [Null,String] as () => string | null}
{type: Any as () => string | null}
{type: [Object,String] as () => string | null} // with null considered an object

Dead Ends

// This will not work because 'Null' is not a type
{type: [Null,String] as () => string | null}
// This will not work because 'Any' is not a type
{type: Any as () => string | null}
// This will not work because null is not considered an Object, although is should be
{type: [Object,String] as () => string | null}
// This will not work because string is not considered an Object
{type: Object as () => string | null}

So I end up doing this, and the Typescript value is now undefined instead of string | null

{
     validator: prop => typeof prop === 'string' || prop === null,
     required: true,
}

@dimitor115
Copy link

@Flamenco
I am using some kind of workaround:

props: {
    status: {
      type: String as PropType<SomeType | null>,
      default: null
    }
  }

The typescript compiler understand this.status as SomeType or null however vue doen't have problems with passing null via prop.

@Volmarg
Copy link

Volmarg commented Nov 7, 2021

Sadly this problem still exists. What's more annoying is the error saying. got Null (first letter is uppercase) but there is only null.

@mspoulsen
Copy link

I think the key here is to use a default value of null:

foo: {
      type: (Object as () => Foo) || null,
      default: null,
    },

This works for me. If I use "required" instead of "default" I get the error mentioned above.

@GordonSo
Copy link

GordonSo commented Dec 7, 2021

Exactly as @dimitor115 and @mspoulsen said.
Also removing the required: true setting is necessary which they already implied in their answers.

@rgrignon1
Copy link

I don't know why is this issue closed and have never been reopened since it has never been fixed.

Setting a default value as null is not the same as explicitly requiring a value that could still be null. Forcing a default value and removing the required param setting is a weak workaround at best and at worst it just doesn't work at all, especially without typescript.

It's a great issue when you need a dynamic prop that is updated often and could be set to null, like a selection component, which is a pretty common use case that has been mentioned by others and is also mine.

@plehnen
Copy link

plehnen commented Nov 14, 2022

vuejs/core#3948

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests