Using a Typescript interface or type as a prop type in VueJS

Mitchell Garcia
Front-End Society
Published in
3 min readMar 7, 2018

As covered in our previous article about Writing Single File Components in Typescript, there’s two ways of creating a “component” in Vue and Typescript: using vue-class-component or Vue.extend.

If you’re using Vue in vanilla Javascript, a prop can only be an “Object,” and you’ll need to manually validate the object has specific keys on it at runtime in order to confirm it is correct.

With Typescript, you actually can take full advantage of Typescript’s static typing with a “Object” Vue prop. This provides you full auto complete on object properties and static checking of a property’s existence at compile time.

How do you do it?

Just cast the Object to a function that returns the interface you’d like it to implement.

In order to access an object as a complex interface types in Vue and Typescript, you must cast it to a function that returns that interface “Object as () => ComplexObjectInterface”

Why Does This Work?

When you pass an Object as a prop type into Vue component, you’re actually passing an Object constructor.

Example validation code to see if ‘test’ is an Object

In order to validate this prop at runtime, Vue runs validation code similar to to what is listed above in order to check that it is in fact an instanceof the “type” provided.

Typescript interfaces do not exist at runtime, so this:

This looks correct, but is not, as Typescript interfaces are only available at runtime (hence why VSCode is so unhappy)

will look like this once it’s compiled to Javascript, hence the squiggly red line:

What the Typescript above will be compiled down to, as Typescript interfaces are not available at runtime.

Casting the Object to your interface also will not work, as your interface does not implement the methods that the native Object constructor does

This will return the following error: “Type ‘ObjectConstructor’ cannot be converted to type ‘ComplexObjectInterface’. Property ‘testProp’ is missing in type ‘ObjectConstructor’.”

The reason this works:

is because Vue’s Typescript typings internally treat any function passed as a ‘type’ as a function that returns an instance of the interface.

The “Prop<T>” returns a union type — if an function is passed into it, it will call that function and by typed as the object returned by that function (see the “T & object” portion).

It’s a little confusing, but to be honest, most things in life are.

Is There A Better Way?

There is an open pull request to expose a PropTypes interface that will allow you to cast the Object constructor to a complex interface, like this:

props: {
testProp: Object as PropTypes<{ test: boolean }>
}

But for now, the only way to type complex prop types without adopting vue-class-component is to cast the Object as a function that returns the interface, like this:

props: {
testProp: Object as () => { test: boolean }
}

Thank you for reading the Front-End Society Blog! You can follow me on Twitter for more content.

--

--