npm create vite@latest
or
npm create vite@latest live-demo --template vue-ts
or
npm init vue@latest
cd live-demo && npm install
"First class" IDE
β Vite does not type check
rely on IDE || run tsc --noEmit
manually
npm run dev
# VITE v4.3.4 ready in 468 ms
# β Local: http://localhost:5173/
# β Network: use --host to expose
# β press h to show help
// !TS: props just passed in as an array
<script setup>
defineProps(['msg']);
</script>
My message: {{ msg }}
// "type-based declaration"
<script lang="ts" setup>
defineProps<{
msg: string,
}>();
</script>
// "runtime declaration"
<script lang="ts" setup>
defineProps({
msg: {
type: String,
required: true,
},
});
</script>
// type-based
withDefaults(defineProps<{
msg?: string,
}>(), {
msg: "Default message",
});
// runtime
defineProps({
msg: {
type: String,
default: "Default message",
},
});
// type-based
withDefaults(defineProps<{
messages: {
title: string,
body: string,
}
}>(), {
messages: () => ({
title: "First message",
body: "Second message"
}),
});
// runtime
import { PropType } from "vue";
defineProps({
messages: {
type: Object as PropType<{
title: string,
body: string,
}>,
default: () => ({
title: "First message",
body: "Second message",
});
},
});
// β
interface Props {
messages: {
title: string,
body: string,
},
};
withDefaults(defineProps<Props>(), {
messages: () => ({
title: "First message",
body: "Second message"
}),
});
// β (for now)
import type { Props } from "./types";
withDefaults(defineProps<Props>(), {
messages: () => ({
title: "First message",
body: "Second message"
}),
});
// β
import type { Props } from "./types";
defineProps({ // ???
// types.ts
// β
export interface Props {
messages: {
title: string,
body: string,
},
};
// β
export interface MessageObject {
title: string,
body: string,
}
import { PropType } from "vue";
import type { MessageObject } from "./types";
defineProps({
messages: {
type: Object as PropType<MessageObject>,
default: () => ({
title: "First message",
body: "Second message"
}),
},
});
import type { MessageObject } from "./types";
withDefaults(defineProps<{
messages: MessageObject,
}>(), {
messages: () => ({
title: "First message",
body: "Second message"
}),
});
emit
, ref
, computed
, oh my!
import { ref } from 'vue'
// inferred type: Ref<number>
const year = ref(2023);
year.value = "2023"; // β
const year = ref<number | string>(2023);
year.value = "2023"; // β
// ContextProvider.vue
provide("count", 0);
// Component.vue
Count: {{ count }}
// Component.vue
const count = inject("count") as number; // π€
// context.ts
import { InjectionKey } from "vue";
export const countKey = Symbol("count") as InjectionKey<number>;
// ContextProvider.vue
import {countKey} from "./context";
provide(countKey, 0);
// Component.vue
import {countKey} from "./context";
const count = inject(countKey);
defineProps
: type-based vs. runtime declaration
ref
typingprovide
/inject
typing<script setup>
vs. non-setup
workflow
emit
, computed
, reactive