Composition-api: [TypeScript]Why are props with required optional?

Created on 17 Aug 2019  Â·  10Comments  Â·  Source: vuejs/composition-api

version: 2.2.0

<script lang="ts">
import { createComponent } from "vue-function-api";

interface Props {
  msg: string;
}

export default createComponent({
  props: ({
    msg: {
      required: true,
    }
  } as unknown) as Props,

  setup(props) {
    return {
      msg: props.msg
    };
  }
});
</script>

スクリーンショット 2019-08-17 17 37 39

Reproduction
https://codesandbox.io/s/vue-template-xt1wt?fontsize=14

Most helpful comment

Check here

You should cast props property as const and add typings on inner props properties

Es.

import { createComponent, PropType } from "vue-function-api";

export default createComponent({
  props: {
    msg: {
      type: String;
      required: true;
    }
  } as const,

  setup(props) {
    return {
      msg: props.msg  // string
    };
  }
});

Notice that, if you need to use a complex object instead of a native type, you should cast the type as type: (Object as unknown) as PropType<MyObjectInterface>

All 10 comments

These are the same result.

<script lang="ts">
import { createComponent } from "vue-function-api";

interface Props {
  msg: string;
}

export default createComponent({
  props: ({
    msg: {}
  } as unknown) as Props,

  setup(props) {
    return {
      msg: props.msg  // string | undefined
    };
  }
});
</script>
<script lang="ts">
import { createComponent } from "vue-function-api";

export default createComponent({
  props: {
    msg: {
      type: String,
      required: true,
    }
  },

  setup(props) {
    return {
      msg: props.msg   // string | undefined
    };
  }
});
</script>

It seems that RequiredKeys expects {requred: true}, but since this is a type, {required: boolean} will come.

https://github.com/vuejs/vue-function-api/blob/a7413ec53021887c90f777c29a88e5c04cff8329/src/ts-api/componentProps.ts#L20-L26

With this definition, msg is string. But, I think this definition is very verbose.

<script lang="ts">
import { createComponent, PropType } from "vue-function-api";

interface Props {
  msg: {
    type: PropType<string>;
    required: true;
  };
}

export default createComponent({
  props: {
    msg: {}
  } as Props,

  setup(props) {
    return {
      msg: props.msg  // string
    };
  }
});
</script>

Check here

You should cast props property as const and add typings on inner props properties

Es.

import { createComponent, PropType } from "vue-function-api";

export default createComponent({
  props: {
    msg: {
      type: String;
      required: true;
    }
  } as const,

  setup(props) {
    return {
      msg: props.msg  // string
    };
  }
});

Notice that, if you need to use a complex object instead of a native type, you should cast the type as type: (Object as unknown) as PropType<MyObjectInterface>

Thx! It was solved.

Is there any solution for this method that was available up to v2.1?

<script lang="ts">
import { createComponent } from "vue-function-api";

interface Props {
  msg: string;
}

export default createComponent({
  props: ({
    msg: {}
  } as unknown) as Props,

  setup(props) {
    return {
      msg: props.msg  // string | undefined
    };
  }
});
</script>

The solution I gave should work even for 2.1, the code you pasted here makes me think you didn't understand well the explanation into the link I provided and the fix I proposed.
You should use this:

import { createComponent } from "vue-function-api";

export default createComponent({
  props: {
    msg: {
      type: String, // Notice that it's not the native `string` type, this one has PascalCase notation
      required: true,
    }
  } as const, // Without this, `props.msg` will be `string | undefined`

  setup(props) {
    return {
      msg: props.msg  // Will be `string`
    };
  }
});

Also note that, AFAIK props are automatically available on template, you don't need to return them from setup() method. In this way you are probably actively overwriting the already available prop

No, I understand.
I want to define a Props type and reference that type from the parent.

In this way.
https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md#typescript-only-props-typing

But Vue.2.x requires props option.
The solution for that was as unknown as Porps.

I may be better off waiting for v3.x for now😔

I'm understand now, but the answer is specified in the first sentence of the paragraph.

In 3.0, the props declaration is optional. If you don't want runtime props validation, you can omit props declaration and declare your expected prop types directly in TypeScript

I think that behaviour will be available only in v3, where Vue core is written in TypeScript itself.

I think so, too.
Thank you for teaching me.

In vue2.x the component can only receive prop declare in props options, so we can't make the props declaration optional with vue2.x.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

spaceemotion picture spaceemotion  Â·  6Comments

ycmjason picture ycmjason  Â·  5Comments

TooBug picture TooBug  Â·  6Comments

banricho picture banricho  Â·  3Comments

SeregPie picture SeregPie  Â·  6Comments