@enp/vue-typed-component
v0.10.2
Published
vue-class-component wrapper to make components more typesafe
Downloads
100
Readme
vue-typed-component
Make vue-class-component more typesafe
Requirement
- TypeScript >= 2.5
- Vue >= 2.5
Breaking changes
- 0.10.0
- Undocumented api
props
has removed. Use vue-strict-prop instead.
- Undocumented api
Install
install from npm:
npm install vue-typed-component -S
and install peer dependencies from npm:
npm install vue vue-class-component vue-tsx-support -S
Example
import * as tc from "vue-typed-component"
interface ToDoProps {
title: string;
done: boolean;
}
interface ToDoEvents {
stateChanged: boolean
}
@tc.component(ToDo /* pass target class itself as first argument */, {
// each prop names and types are checked by compiler
props: {
title: { type: String, required: true },
done: { type: Boolean, default: false }
},
template: `
<div @click="clicked">
<span :style="style">{{ title }}</span>
</div>
`
})
class ToDo extends tc.EvTypedComponent<ToDoProps, ToDoEvents> {
// If events are not needed,
// use TypedComponent<Props> instead
get style() {
// Access each props via `$props`
if (this.$props.done) {
return { textDecoration: "line-through" };
}
else {
return {}
}
}
clicked() {
// Emit events via `$events.emit()`.
// event name and argument type are checked by compiler.
// `$events.on`, `$events.once`, and `$events.off` are also available.
this.$events.emit("stateChanged", !this.$props.done);
}
}
You can specify type parameters explicitly instead of passing target class as first argument. (just for backward compatibility)
@tc.component<ToDoProps, ToDo>({
props: {
title: { type: String, required: true },
done: { type: Boolean, default: false }
},
template: `
<div @click="clicked">
<span :style="style">{{ title }}</span>
</div>
`
})
class ToDo extends tc.EvTypedComponent<ToDoProps, ToDoEvents> {
/* snip */
}
If you want to define component with $data
, use VueStatefulComponent
instead.
import * as tc from "vue-typed-component"
interface ToDoProps {
title: string;
}
interface ToDoData {
done: boolean;
}
@tc.component(ToDo, {
// each prop names are checked by compiler
props: {
title: { type: String, required: true }
},
template: `
<div @click="clicked">
<span :style="style">{{ title }}</span>
</div>
`
})
class ToDo extends tc.StatefulTypedComponent<ToDoProps, ToDoData> {
// If events are needed,
// use StatefulEvTypedComponent<Props, Events, Data> instead
// data() method existance and return type of it are checked by compiler
data() {
return { done: false };
}
get style() {
// Access each data via `$data`
if (this.$data.done) {
return { textDecoration: "line-through" };
}
else {
return {};
}
}
clicked() {
this.$data.done = !this.$data.done;
}
}
Helper function to define functional component is also in.
Duprecated : because Vue.extend
is now type-safe enough for functional component
import * as tc from "vue-typed-component"
interface ToDoProps {
id: string;
title: string;
}
const ToDo = tc.functionalComponent<ToDoProps>(
"ToDo",
{
id: { type: String, required: true },
title: { type: String, required: true }
},
(h, { props }) => {
return h("span", { attrs: { id: props.id } }, [ props.title ]);
}
);