Skip to content

Commit eb514b6

Browse files
authored
Merge pull request #10 from typescript-cheatsheets/chiubaca-brain-dump
Docs Reshuffle & Mini Brain Dump
2 parents 51282d2 + 81e087e commit eb514b6

File tree

3 files changed

+192
-67
lines changed

3 files changed

+192
-67
lines changed

README.md

Lines changed: 41 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Cheatsheets for experienced Vue developers getting started with TypeScript.
44

55
- [Vue 3 specifics](vue-3.md)
6+
- [Class Components & Decorators](class-components.md)
67

78
# Section 1: Setup
89

@@ -87,66 +88,6 @@ const Component = defineComponent({
8788
});
8889
```
8990

90-
### Class Components
91-
[Vue Class Components](https://class-component.vuejs.org/) offers an alternative class-style syntax for Vue components which integrates well with TypeScript.
92-
93-
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).
94-
95-
96-
To get started with both libraries in your existing Vue project, run:
97-
```
98-
npm install vue-class-component vue-property-decorator
99-
```
100-
101-
You only need to import `vue-property-decorator` into your `.vue` file as it extends `vue-class-component`.
102-
103-
You can now write TS in your components like this:
104-
105-
```vue
106-
<template>
107-
<div>
108-
{{ count }}
109-
<button v-on:click="increment">+</button>
110-
<button v-on:click="decrement">-</button>
111-
{{ computedValue }}
112-
</div>
113-
</template>
114-
115-
<script lang="ts">
116-
import { Vue, Component } from "vue-property-decorator";
117-
118-
@Component
119-
export default class Hello extends Vue {
120-
121-
count: number = 0
122-
vue: string = "vue"
123-
ts: string = "ts"
124-
125-
// Lifecycle methods can be accessed like this
126-
mounted() {
127-
console.log('component mounted')
128-
}
129-
130-
// Method are component methods
131-
increment(): void {
132-
this.count++
133-
}
134-
135-
decrement(): void {
136-
this.count--
137-
}
138-
139-
// Computed values are getters
140-
get computedValue(): string {
141-
return `${vue} and ${ts} rocks!`
142-
}
143-
}
144-
</script>
145-
```
146-
See the [full guide for Vue Class Components](https://class-component.vuejs.org/guide/class-component.html#data).
147-
148-
> _Class components should not confused with the now abandoned [Class API proposal](https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121)._
149-
15091
## Props
15192

15293
`PropType` can be used to annotate props with a particular object shape.
@@ -176,26 +117,34 @@ export default Vue.extend({
176117
</script>
177118
```
178119

179-
With vue-class-components and vue-property-decorator, you can use the `Prop` decorator:
120+
Alternatively, you can also annote your prop types with an anonymous function:
180121

181122
```vue
123+
import Vue from 'vue'
124+
182125
<script lang="ts">
183-
import { Vue, Component, Prop } from "vue-property-decorator";
126+
import Vue from "vue";
184127
185128
interface PersonInfo {
186129
firstName: string,
187130
surname: string,
188131
age: number
189132
}
190133
191-
@Component
192-
export default class InfoCard extends Vue {
193-
@Prop({ required: true }) readonly info: PersonInfo;
194-
}
134+
export default Vue.extend({
135+
136+
name: "InfoCard",
137+
props: {
138+
info: {
139+
type: Object as () => PersonInfo,
140+
required: true
141+
}
142+
}
143+
});
195144
</script>
196145
```
197146

198-
## Data Properties
147+
## Data Properties (Options API)
199148

200149
You can enforce types on Vue data properties by annotating the return data object:
201150

@@ -242,6 +191,31 @@ export default Vue.extend({
242191
```
243192
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.
244193

194+
## Computed Properties (Options API)
195+
196+
Typing the return type for your computed properties is important especially when `this` is involved as TypeScript sometimes has trouble infering the type.
197+
198+
```ts
199+
200+
export default Vue.extend({
201+
data() {
202+
return {
203+
name: 'World',
204+
}
205+
},
206+
computed: {
207+
greet(): string { //👈 Remember to annotate your computed properties like so.
208+
return 'Hello ' + this.name
209+
},
210+
}
211+
})
212+
213+
```
214+
215+
>
216+
217+
245218
# Other Vue + TypeScript resources
246219
- Views on Vue podcast - https://devchat.tv/views-on-vue/vov-076-typescript-tell-all-with-jack-koppa/
247220
- Focuses a lot on class components and vue-property-decorator - https://blog.logrocket.com/how-to-write-a-vue-js-app-completely-in-typescript/
221+
- Vue 3 Hooks and Type Safety with TypeScript - https://www.youtube.com/watch?v=aJdi-uEKYAc

class-components.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Class Components
2+
3+
## Overview
4+
5+
[Vue Class Components](https://class-component.vuejs.org/) offers an alternative class-style syntax for Vue components which integrates well with TypeScript.
6+
7+
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).
8+
9+
10+
To get started with both libraries in your existing Vue project, run:
11+
```
12+
npm install vue-class-component vue-property-decorator
13+
```
14+
15+
You only need to import `vue-property-decorator` into your `.vue` file as it extends `vue-class-component`.
16+
17+
You can now write TS in your components like this:
18+
19+
```vue
20+
<template>
21+
<div>
22+
{{ count }}
23+
<button v-on:click="increment">+</button>
24+
<button v-on:click="decrement">-</button>
25+
{{ computedValue }}
26+
</div>
27+
</template>
28+
29+
<script lang="ts">
30+
import { Vue, Component } from "vue-property-decorator";
31+
32+
@Component
33+
export default class Hello extends Vue {
34+
35+
count: number = 0
36+
vue: string = "vue"
37+
ts: string = "ts"
38+
39+
// Lifecycle methods can be accessed like this
40+
mounted() {
41+
console.log('component mounted')
42+
}
43+
44+
// Method are component methods
45+
increment(): void {
46+
this.count++
47+
}
48+
49+
decrement(): void {
50+
this.count--
51+
}
52+
53+
// Computed values are getters
54+
get computedValue(): string {
55+
return `${vue} and ${ts} rocks!`
56+
}
57+
}
58+
</script>
59+
```
60+
See the [full guide for Vue Class Components](https://class-component.vuejs.org/guide/class-component.html#data).
61+
62+
> _Class components should not confused with the now abandoned [Class API proposal](https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121)._
63+
64+
## Props
65+
You can use the `Prop` decorator to annoate your prop types like so:
66+
67+
```ts
68+
<script lang="ts">
69+
import { Vue, Component, Prop } from "vue-property-decorator";
70+
71+
interface PersonInfo {
72+
firstName: string,
73+
surname: string,
74+
age: number
75+
}
76+
77+
@Component
78+
export default class InfoCard extends Vue {
79+
@Prop() readonly info!: PersonInfo;
80+
@Prop({ default: false }) readonly admin?: boolean;
81+
}
82+
</script>
83+
```
84+
Is equivalent to:
85+
86+
```ts
87+
import Vue from "vue-property-decorator";
88+
import Vue, { PropType } from 'vue'
89+
90+
interface PersonInfo {
91+
firstName: string,
92+
surname: string,
93+
age: number
94+
}
95+
export default {
96+
props: {
97+
info: {
98+
type: Object as PropType<PersonInfo>,
99+
required: true
100+
},
101+
admin: {
102+
type: Boolean,
103+
default: false
104+
}
105+
},
106+
}
107+
108+
```

vue-3.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,46 @@ declare const props: {
3030
3131
export const welcome = computed(() => `Welcome, ${props.name}!`)
3232
```
33+
34+
## Composition API
35+
36+
### Refs
37+
38+
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:
39+
40+
```ts
41+
import {ref} from "vue"
42+
43+
interface PersonInfo {
44+
firstName: string,
45+
surname: string,
46+
age: number
47+
}
48+
49+
const people = ref<PersonInfo[]>([])
50+
51+
```
52+
53+
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.
54+
55+
```ts
56+
57+
import { ref, Ref } from "vue";
58+
59+
type ApiRequest = () => Promise<void>;
60+
61+
// When using this function we can supply the type via generics
62+
export function useAPI<T>(url: RequestInfo, options?: RequestInit) {
63+
64+
const response = ref() as Ref<T>; // 👈 note we're typing our ref using `as`
65+
66+
const request: ApiRequest = async () => {
67+
const resp = await fetch(url, options);
68+
const data = await resp.json();
69+
response.value = data;
70+
};
71+
72+
return { response, request };
73+
}
74+
75+
```

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy