or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcomponent-utilities.mdcomputed.mddependency-injection.mdindex.mdlifecycle.mdreactive-state.mdtypes.mdwatchers.md

computed.mddocs/

0

# Computed Properties

1

2

Derived reactive state that automatically updates when dependencies change. Computed properties provide cached, derived values that recalculate only when their reactive dependencies change.

3

4

## Capabilities

5

6

### Read-only Computed

7

8

Creates a computed property with a getter function that automatically tracks dependencies and caches results.

9

10

```typescript { .api }

11

/**

12

* Creates a read-only computed property

13

* @param getter - Function that computes the value

14

* @returns Read-only computed reference

15

*/

16

function computed<T>(getter: ComputedGetter<T>): ComputedRef<T>;

17

18

type ComputedGetter<T> = () => T;

19

20

interface ComputedRef<T = any> extends WritableComputedRef<T> {

21

readonly value: T;

22

}

23

```

24

25

**Usage Examples:**

26

27

```typescript

28

import { ref, computed } from "@vue/composition-api";

29

30

const count = ref(0);

31

const doubleCount = computed(() => count.value * 2);

32

33

console.log(doubleCount.value); // 0

34

count.value = 5;

35

console.log(doubleCount.value); // 10

36

37

// Complex computed with multiple dependencies

38

const firstName = ref("John");

39

const lastName = ref("Doe");

40

const fullName = computed(() => `${firstName.value} ${lastName.value}`);

41

42

console.log(fullName.value); // "John Doe"

43

```

44

45

### Writable Computed

46

47

Creates a computed property with both getter and setter functions, allowing two-way binding and derived state manipulation.

48

49

```typescript { .api }

50

/**

51

* Creates a writable computed property

52

* @param options - Object with get and set functions

53

* @returns Writable computed reference

54

*/

55

function computed<T>(options: WritableComputedOptions<T>): WritableComputedRef<T>;

56

57

interface WritableComputedOptions<T> {

58

get: ComputedGetter<T>;

59

set: ComputedSetter<T>;

60

}

61

62

type ComputedSetter<T> = (value: T) => void;

63

64

interface WritableComputedRef<T> extends Ref<T> {

65

readonly effect: ReactiveEffect<T>;

66

}

67

```

68

69

**Usage Examples:**

70

71

```typescript

72

import { ref, computed } from "@vue/composition-api";

73

74

const firstName = ref("John");

75

const lastName = ref("Doe");

76

77

const fullName = computed({

78

get: () => `${firstName.value} ${lastName.value}`,

79

set: (value: string) => {

80

const parts = value.split(" ");

81

firstName.value = parts[0] || "";

82

lastName.value = parts[1] || "";

83

},

84

});

85

86

console.log(fullName.value); // "John Doe"

87

88

// Setting the computed value updates the underlying refs

89

fullName.value = "Jane Smith";

90

console.log(firstName.value); // "Jane"

91

console.log(lastName.value); // "Smith"

92

```

93

94

### Advanced Computed Patterns

95

96

Advanced usage patterns for computed properties including conditional logic, async operations, and error handling.

97

98

**Conditional Computed:**

99

100

```typescript

101

import { ref, computed } from "@vue/composition-api";

102

103

const user = ref<{ name: string; email?: string } | null>(null);

104

const displayName = computed(() => {

105

if (!user.value) return "Guest";

106

return user.value.email ? `${user.value.name} (${user.value.email})` : user.value.name;

107

});

108

109

// Computed with fallback values

110

const safeValue = computed(() => user.value?.name ?? "Unknown");

111

```

112

113

**Computed with Complex Logic:**

114

115

```typescript

116

import { ref, reactive, computed } from "@vue/composition-api";

117

118

const items = ref([

119

{ id: 1, name: "Apple", category: "fruit", price: 1.2 },

120

{ id: 2, name: "Banana", category: "fruit", price: 0.8 },

121

{ id: 3, name: "Carrot", category: "vegetable", price: 0.6 },

122

]);

123

124

const filters = reactive({

125

category: "",

126

maxPrice: null as number | null,

127

searchTerm: "",

128

});

129

130

const filteredItems = computed(() => {

131

return items.value.filter((item) => {

132

const matchesCategory = !filters.category || item.category === filters.category;

133

const matchesPrice = !filters.maxPrice || item.price <= filters.maxPrice;

134

const matchesSearch = !filters.searchTerm ||

135

item.name.toLowerCase().includes(filters.searchTerm.toLowerCase());

136

137

return matchesCategory && matchesPrice && matchesSearch;

138

});

139

});

140

141

const itemStats = computed(() => ({

142

total: filteredItems.value.length,

143

avgPrice: filteredItems.value.reduce((sum, item) => sum + item.price, 0) / filteredItems.value.length || 0,

144

categories: [...new Set(filteredItems.value.map(item => item.category))],

145

}));

146

```

147

148

**Computed with Side Effects (Anti-pattern Warning):**

149

150

```typescript

151

import { ref, computed, watch } from "@vue/composition-api";

152

153

// ❌ Don't do this - computed should be pure

154

const badComputed = computed(() => {

155

console.log("This runs on every access!"); // Side effect

156

return someValue.value * 2;

157

});

158

159

// ✅ Use watchers for side effects instead

160

const someValue = ref(0);

161

const doubledValue = computed(() => someValue.value * 2);

162

163

watch(doubledValue, (newValue) => {

164

console.log("Doubled value changed:", newValue);

165

});

166

```

167

168

### Performance Considerations

169

170

Computed properties are cached and only recalculate when dependencies change, making them efficient for expensive operations.

171

172

```typescript

173

import { ref, computed } from "@vue/composition-api";

174

175

const expensiveData = ref([/* large array */]);

176

177

// This computation only runs when expensiveData changes

178

const processedData = computed(() => {

179

console.log("Processing data..."); // Only logs when dependencies change

180

return expensiveData.value

181

.filter(item => item.active)

182

.map(item => ({ ...item, processed: true }))

183

.sort((a, b) => a.priority - b.priority);

184

});

185

186

// Multiple accesses use the cached result

187

console.log(processedData.value); // Processes data

188

console.log(processedData.value); // Uses cache

189

console.log(processedData.value); // Uses cache

190

```

191

192

### Computed in Component Setup

193

194

Typical usage patterns within Vue component setup functions.

195

196

```typescript

197

import { defineComponent, ref, computed } from "@vue/composition-api";

198

199

export default defineComponent({

200

props: {

201

multiplier: {

202

type: Number,

203

default: 1,

204

},

205

},

206

setup(props) {

207

const baseValue = ref(10);

208

209

// Computed property using props and reactive state

210

const computedValue = computed(() => baseValue.value * props.multiplier);

211

212

// Computed property for template usage

213

const isEven = computed(() => computedValue.value % 2 === 0);

214

215

// Writable computed for v-model compatibility

216

const doubledBase = computed({

217

get: () => baseValue.value * 2,

218

set: (value) => {

219

baseValue.value = value / 2;

220

},

221

});

222

223

return {

224

baseValue,

225

computedValue,

226

isEven,

227

doubledBase,

228

};

229

},

230

});

231

```

232

233

## Types

234

235

```typescript { .api }

236

interface ComputedRef<T = any> extends WritableComputedRef<T> {

237

readonly value: T;

238

}

239

240

interface WritableComputedRef<T> extends Ref<T> {

241

readonly effect: ReactiveEffect<T>;

242

}

243

244

interface WritableComputedOptions<T> {

245

get: ComputedGetter<T>;

246

set: ComputedSetter<T>;

247

}

248

249

type ComputedGetter<T> = () => T;

250

type ComputedSetter<T> = (value: T) => void;

251

252

interface ReactiveEffect<T = any> {

253

(): T;

254

_isEffect: true;

255

id: number;

256

active: boolean;

257

raw: () => T;

258

deps: Array<Dep>;

259

options: ReactiveEffectOptions;

260

}

261

262

interface ReactiveEffectOptions {

263

lazy?: boolean;

264

scheduler?: (job: ReactiveEffect) => void;

265

onTrack?: (event: DebuggerEvent) => void;

266

onTrigger?: (event: DebuggerEvent) => void;

267

onStop?: () => void;

268

}

269

```