How to use `null` to define an empty ref in Vue 3 & TypeScript?

Viewed 1964

I am using Vue 3 and TypeScript with the script setup tag (<script setup lang="ts">.

And I often have a ref inside a composable that looks like this:

const composableMessage = ref<string | null>(null);

It's a string or a number or something with an inital "empty" value. And I am intentionally using null instead of undefined to define "empty" because I prefer it.

Then I have a child component with a prop that looks like this:

defineProps({
  messageProp: {
    type: String,
    required: false,
    default: '',
  },
});

And when using it in a parent component like this:

import myComposable from '/src/composables/myComposable';
const { composableMessage } = myComposable();
<my-component :messageProp="composableMessage" />

I get this TypeScript error on :messageProp:

Type 'string | null' is not assignable to type 'string | undefined'.
  Type 'null' is not assignable to type 'string | undefined'.ts(2322)

If I use const composableMessage = ref<string | undefined>(undefined); the TypeScript error goes away, but I would much rather keep it as null.

Why am I forced into using undefined for empty refs?

Is there a way around this?

1 Answers

It's the other way around, your messageProp accepts only string or undefined due to the required: false, but you try to send it string or null.

The link I sent as comment VueJS Using Prop Type Validation With NULL and 'undefined' Values? does not seem to work with Vue3 and Volar/Typescript.

So to accept null you should change the prop type of messageProp as follows

defineProps({
  messageProp: {
    type: String as PropType<string|null>,
    required: false,
    default: '',
  },
});

(note: I do not expect the default value ('') to be set for null, only undefined, so you'd probably need to handle the null value yourself)

(note2: you do not need to write ref<string | undefined>(undefined) you'd get the same Ref<string|undefined> object with ref<string>())

Related