diff --git a/README.md b/README.md index 42d4e71..0d7ea93 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Cheatsheets for experienced Vue developers getting started with TypeScript. - [Vue 3 specifics](vue-3.md) +- [Class Components & Decorators](class-components.md) # Section 1: Setup @@ -87,66 +88,6 @@ const Component = defineComponent({ }); ``` -### Class Components -[Vue Class Components](https://class-component.vuejs.org/) offers an alternative class-style syntax for Vue components which integrates well with TypeScript. - -To have consistent support for decorators in your Vue components, it's also recommended to install [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator). - - -To get started with both libraries in your existing Vue project, run: -``` -npm install vue-class-component vue-property-decorator -``` - -You only need to import `vue-property-decorator` into your `.vue` file as it extends `vue-class-component`. - -You can now write TS in your components like this: - -```vue - - - -``` -See the [full guide for Vue Class Components](https://class-component.vuejs.org/guide/class-component.html#data). - -> _Class components should not confused with the now abandoned [Class API proposal](https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121)._ - ## Props `PropType` can be used to annotate props with a particular object shape. @@ -176,11 +117,13 @@ export default Vue.extend({ ``` -With vue-class-components and vue-property-decorator, you can use the `Prop` decorator: +Alternatively, you can also annote your prop types with an anonymous function: ```vue +import Vue from 'vue' + ``` -## Data Properties +## Data Properties (Options API) You can enforce types on Vue data properties by annotating the return data object: @@ -242,6 +191,31 @@ export default Vue.extend({ ``` Note that [type assertion](https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions) like this does not provide any type safety. If for example, the `contents` property was missing in `newPost`, TypeScript would not catch this error. +## Computed Properties (Options API) + +Typing the return type for your computed properties is important especially when `this` is involved as TypeScript sometimes has trouble infering the type. + +```ts + +export default Vue.extend({ + data() { + return { + name: 'World', + } + }, + computed: { + greet(): string { //👈 Remember to annotate your computed properties like so. + return 'Hello ' + this.name + }, + } +}) + +``` + +> + + # Other Vue + TypeScript resources - Views on Vue podcast - https://devchat.tv/views-on-vue/vov-076-typescript-tell-all-with-jack-koppa/ - Focuses a lot on class components and vue-property-decorator - https://blog.logrocket.com/how-to-write-a-vue-js-app-completely-in-typescript/ +- Vue 3 Hooks and Type Safety with TypeScript - https://www.youtube.com/watch?v=aJdi-uEKYAc diff --git a/class-components.md b/class-components.md new file mode 100644 index 0000000..4e403c3 --- /dev/null +++ b/class-components.md @@ -0,0 +1,108 @@ +# Class Components + +## Overview + +[Vue Class Components](https://class-component.vuejs.org/) offers an alternative class-style syntax for Vue components which integrates well with TypeScript. + +To have consistent support for decorators in your Vue components, it's also recommended to install [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator). + + +To get started with both libraries in your existing Vue project, run: +``` +npm install vue-class-component vue-property-decorator +``` + +You only need to import `vue-property-decorator` into your `.vue` file as it extends `vue-class-component`. + +You can now write TS in your components like this: + +```vue + + + +``` +See the [full guide for Vue Class Components](https://class-component.vuejs.org/guide/class-component.html#data). + +> _Class components should not confused with the now abandoned [Class API proposal](https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121)._ + +## Props +You can use the `Prop` decorator to annoate your prop types like so: + +```ts + +``` +Is equivalent to: + +```ts +import Vue from "vue-property-decorator"; +import Vue, { PropType } from 'vue' + +interface PersonInfo { + firstName: string, + surname: string, + age: number +} +export default { + props: { + info: { + type: Object as PropType, + required: true + }, + admin: { + type: Boolean, + default: false + } + }, +} + +``` \ No newline at end of file diff --git a/vue-3.md b/vue-3.md index 62b93bb..5192996 100644 --- a/vue-3.md +++ b/vue-3.md @@ -30,3 +30,46 @@ declare const props: { export const welcome = computed(() => `Welcome, ${props.name}!`) ``` + +## Composition API + +### Refs + +Vue can infer the type of your `ref`'s but if you need to represent some more complex types you can do so with generics: + +```ts +import {ref} from "vue" + +interface PersonInfo { + firstName: string, + surname: string, + age: number +} + +const people = ref([]) + +``` + +Alternatively you can use casting with `as`. This should be used if the type is unknown. Consider this example where we create a composition wrapper function around `fetch` and we dont know the data structure that will be returned. + +```ts + +import { ref, Ref } from "vue"; + +type ApiRequest = () => Promise; + +// When using this function we can supply the type via generics +export function useAPI(url: RequestInfo, options?: RequestInit) { + + const response = ref() as Ref; // 👈 note we're typing our ref using `as` + + const request: ApiRequest = async () => { + const resp = await fetch(url, options); + const data = await resp.json(); + response.value = data; + }; + + return { response, request }; +} + +``` \ No newline at end of file