Default props in Vue 3 composition api are undefined (TS)

985 views Asked by At

If I don't pass a value, the prop is just undefined, instead of taking the default value.

For example switchView and activeView. I have defined the props like this:

interface Props {
  config: {
    switchView?: boolean;
    activeView?: number;
    urls: {
      someUrl: string;
    };
    labels?: {
      someLabels: string;
    };
  };
}

const props = withDefaults(defineProps<Props>(), {
  config: () => ({
    switchView: true,
    activeView: 0,
    urls: {
      someUrl: '',
    },
    labels: {
      someLabel: '',
    },
  }),
});

And in the parent component, I'm passing the prop config object like so:

const config = {
  urls: {
    someUrl: '/example',
  },
  labels: {
    someLabel: 'Example label',
  },
};

And in my Vue Dev Tools I only see the passed props, but none of the default values that I've set. What am I doing wrong?

If I pass them in the config object, I get them as a prop. But I expect if I don't pass those optional values, then the defaults will take place.

2

There are 2 answers

0
Bushima On BEST ANSWER

I found the issue. Vue has a problem with nested props, more specifically, the parent config object is the problem. By removing it it works fine.

interface Props {
  switchView?: boolean;
  activeView?: number;
  urls: {
    someUrl: string;
  };
  labels?: {
    someLabel: string;
  };
}

const props = withDefaults(defineProps<Props>(), {
  switchView: true,
  activeView: 0,
  urls: () => ({
    someUrl: '',
  }),
  labels: () => ({
    someLabel: '',
  }),
});
0
Abhinav Kumar On

So, when you use switchView?: boolean to declare the property in the interface. It basically means the property is optional in the interface.

So, JS does not care about it value, at the moment it only care about it's type enforcement to be applied or not. If it optional and you are not passing it or by mistake missed it.

JS never complain about it because it optional. If it is not optional. JS quickly complain 'switchView' is missing on the object.

TLDR version: It doesn't have any relation with its value. So if you do not pass it. It always take undefined

You need to use withDefaults when you are creating the config. So that config variable go through the initialisation process and assigned the default value at the time of declaration.

Might be something like this

let config: Props = withDefaults({}) // so this return initial object with default value
// update the object
config.urls.someUrl = "/example";
config.labels.someLabel = "Example label";

In short your initialisation process is missing in between.