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

Add ability to define required nullable props #3948

Closed
aantipov opened this issue Jun 13, 2021 · 11 comments
Closed

Add ability to define required nullable props #3948

aantipov opened this issue Jun 13, 2021 · 11 comments
Labels
has workaround A workaround has been found to avoid the problem need guidance The approach/solution in the PR is unclear and requires guidance from maintainer to proceed further. ✨ feature request New feature or request

Comments

@aantipov
Copy link

What problem does this feature solve?

I haven't found a way to properly define required nullable props.

Why

I want to be able to define a component property that is required and accepts null as a value (along with "normal" types like String, Number, etc.)

I consider null as a value, which indicates an absence of a value.
undefined means the value is unknown (e.g. we don't know it yet because we haven't got a response from API request).
Hence, null and undefined should not be treated the same.

Problems with current workarounds

1. Marking the property as optional.

  1. If there is a bug in the code and a parent component does not specify the property at all, then I won't get any warnings from Vue.
  2. If there is a bug in the code and a parent component provides undefined as a value, then I won't get any warnings from Vue.
  3. Typescript complains about the following code
props: {
  category: {
    type: String,
    required: false,
  }
},
setup(props) {
  const { category } = toRefs(props);
  console.log(category.value)

because TS considers category as possibly 'undefined'
image (1)

2. Mark the prop as required and hint TS about possible values

props: {
  category: {
    type: String as () => string | null,
    required: true,
  }
}

I get Vue warnings in the console "[Vue warn]: Invalid prop: type check failed for prop “category”. Expected String with value “null”, got Null"

What does the proposed API look like?

I have 2 ideas:

  1. Adding null to the list of possible type values https://v3.vuejs.org/guide/component-props.html#type-checks

So that I can define the prop the following way:

props: {
  category: {
    type: [String, null],
    required: true,
  }
}
  1. Adding nullable option to the prop object (https://v3.vuejs.org/api/options-data.html#props):
props: {
  category: {
    type: String,
    required: true,
    nullable: true,
  }
}
@posva
Copy link
Member

posva commented Jun 14, 2021

You can use a validator: (v: any) => typeof v === 'string' || v === null and remove the type:

    category: {
      required: true,
      type: null as unknown as PropType<string | null>,
      validator: (v: any) => typeof v === 'string' || v === null,
    }

Screenshot 2021-06-14 at 09 39 22

I'm not sure this is the intended way. It's probably worth adding this to docs.

I opened this PR https://github.com/vuejs/vue/pull/9358/files for Vue 2 but we didn't get anywhere with it. I personally would prefer being able to do type: [String, null] but as pointed out here it does create an inconsistency with type: null which currently allows anything (as allowing a prop only when it's null makes no sense)

@posva posva added ✨ feature request New feature or request has workaround A workaround has been found to avoid the problem need guidance The approach/solution in the PR is unclear and requires guidance from maintainer to proceed further. labels Jun 14, 2021
@jacekkarczmarczyk
Copy link
Contributor

type: null which currently allows anything (as allowing a prop only when it's null makes no sense)

On the other hand [whatever, null] doesn't make sense as well, if null means "anything" then adding other types to the array is pointless. And because of that it's very unlikely that it would be a breaking change for anyone

@aantipov
Copy link
Author

@posva Thank you a lot for the workaround 👍 I didn't know I can set type to null. It gives me what I wanted to achieve.

Yet, having built-in support for that would of course be nice!

Ok, I see the problem with [whatever, null] as null is already used and has a different meaning.

Then what about the second variant:

props: {
  myProp: {
    type: String,
    required: true,
    nullable: true,
  }
}

To me, it kinda makes sense:

  1. type is used for defining the Type of values the property should accept
  2. null is used to denote the absence of a value, hence it's better not to treat it as a separate type, but rather as an enhancement of any other type.

Pros/cons for nullable?

@dreadkopp
Copy link

@posva saved my day! thanks mate!

this issue went quite stale. any progress on that in sight ?

@tassin-gauthier
Copy link

Up, this issue is really annoying for the code readability and maintainability. We have two options for now :

  • use type: null as unknown as PropType<string | null>, which is hard to read and sounds wrong, because the real prop type is a string but nullable.

  • do not use required: true and replace it by default: null, which create a change between the developer needs and what the code is doing in reality. For example, i use a state management library, a component is listening a property from that state and passing it to a child component. I want to set the default value to null in my state, because the state should be my single source of truth. The default: null solution is breaking this rule because the real default value is not coming from my state, but from the component itself...

@dreadkopp
Copy link

bump

@kentliau
Copy link

kentliau commented May 23, 2023

Facing this problem as well, the database/json definitely have a lot of null, so I think ability to make a props type nullable is quite important

type: null as unknown as PropType<string | null> is my current workaround for my component.

I use Quasar, they export another type definition to make string | null | undefined possible.

@darylblake
Copy link

The current work around is a bit silly but the only way to remove all the warnings etc. Would it be worthwhile having another PropType primitive like NullablePropType? such as type: Object as NullablePropType<MyType> instead of writing type: null as unknown as Object as PropType<MyType|null>

@sxzz
Copy link
Member

sxzz commented Jun 12, 2023

ATM, we can try the solution below. It has type validation and absent checking.

For <script setup lang="ts">

const props = defineProps({
  msg: {
    type: [Boolean, null] as PropType<boolean | null>,
    required: true
  }
})

// or using type declaration
const props = defineProps<{
  msg: boolean | null
}>()

props.msg
//    ^ boolean | null

TS:

defineComponent({
  props: {
    msg: {
      type: [Boolean, null] as PropType<boolean | null>,
      required: true
    }
  },
  setup(props) {
    props.msg
    //    ^ boolean | null
  }
})

@bseib
Copy link

bseib commented Jan 27, 2024

How about this proposed syntax:

props: {
  category: {
    type: String,
    nullable: true,
    required: false,
  }
},

@yyx990803
Copy link
Member

yyx990803 commented Apr 25, 2024

Somehow missed this when we landed bbf6ca9, which effectively implements proposed solution 1 (which is why the workaround suggested by @sxzz works). Added this detail to the docs in vuejs/docs@26666c0

For non-required props, they are already nullable in the first place.

yyx990803 added a commit to vuejs/docs that referenced this issue Apr 25, 2024
splendente added a commit to splendente/docs-ja that referenced this issue Apr 25, 2024
jay-es pushed a commit to vuejs-translations/docs-ja that referenced this issue Apr 26, 2024
@github-actions github-actions bot locked and limited conversation to collaborators May 10, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has workaround A workaround has been found to avoid the problem need guidance The approach/solution in the PR is unclear and requires guidance from maintainer to proceed further. ✨ feature request New feature or request
Projects
None yet
Development

No branches or pull requests

10 participants