or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-transformation.mddecorator-support.mdexterns-generation.mdindex.mdjsdoc-processing.mdmodule-system.mdpath-utilities.mdtransformer-utilities.mdtype-translation.md

decorator-support.mddocs/

0

# Decorator Support

1

2

Handles decorator downleveling and output transformation for Closure Compiler property renaming compatibility, ensuring decorators work correctly with advanced optimization.

3

4

## Capabilities

5

6

### Decorator Downlevel Transformer

7

8

Main transformer for converting TypeScript decorators to ES5-compatible function calls.

9

10

```typescript { .api }

11

/**

12

* Main transformer factory for downleveling decorators

13

*/

14

function decoratorDownlevelTransformer(

15

typeChecker: ts.TypeChecker,

16

diagnostics: ts.Diagnostic[]

17

): ts.TransformerFactory<ts.SourceFile>;

18

```

19

20

**Usage Example:**

21

22

```typescript

23

import { decoratorDownlevelTransformer } from "tsickle";

24

25

const transformer = decoratorDownlevelTransformer(typeChecker, diagnostics);

26

27

// The transformer converts:

28

// @Component({ selector: 'app' })

29

// class AppComponent {}

30

//

31

// To:

32

// let AppComponent = class AppComponent {};

33

// AppComponent = __decorate([Component({ selector: 'app' })], AppComponent);

34

```

35

36

### Decorator Decision Logic

37

38

Function to determine whether a decorator should be downleveled based on its type and usage.

39

40

```typescript { .api }

41

/**

42

* Determines if decorator should be downleveled

43

*/

44

function shouldLower(decorator: ts.Decorator, typeChecker: ts.TypeChecker): boolean;

45

```

46

47

**Usage Example:**

48

49

```typescript

50

import { shouldLower } from "tsickle";

51

52

// Check if a decorator needs downleveling

53

const needsDownleveling = shouldLower(decoratorNode, typeChecker);

54

55

if (needsDownleveling) {

56

// Apply downleveling transformation

57

console.log("Decorator will be downleveled for Closure compatibility");

58

}

59

```

60

61

### Exporting Decorator Detection

62

63

Functions for identifying decorators that should preserve export information.

64

65

```typescript { .api }

66

/**

67

* Checks if node has an exporting decorator

68

*/

69

function hasExportingDecorator(node: ts.Node, typeChecker: ts.TypeChecker): boolean;

70

71

/**

72

* Returns declarations for a decorator

73

*/

74

function getDecoratorDeclarations(

75

decorator: ts.Decorator,

76

typeChecker: ts.TypeChecker

77

): ts.Declaration[];

78

```

79

80

**Usage Example:**

81

82

```typescript

83

import { hasExportingDecorator, getDecoratorDeclarations } from "tsickle";

84

85

// Check if a class has exporting decorators

86

if (hasExportingDecorator(classNode, typeChecker)) {

87

// This class will be marked for export preservation

88

const declarations = getDecoratorDeclarations(decoratorNode, typeChecker);

89

console.log(`Found ${declarations.length} decorator declarations`);

90

}

91

```

92

93

## Closure Property Renaming Support

94

95

### Property Renaming Transformer

96

97

Transformer that handles decorator output for Closure Compiler property renaming.

98

99

```typescript { .api }

100

/**

101

* Transforms decorator output for Closure property renaming

102

*/

103

function transformDecoratorsOutputForClosurePropertyRenaming(

104

diagnostics: ts.Diagnostic[]

105

): ts.TransformerFactory<ts.SourceFile>;

106

```

107

108

This transformer ensures that decorator metadata is preserved through Closure Compiler's property renaming process.

109

110

### JSDoc Decorator Transformer

111

112

Transformer for processing decorator-related JSDoc comments.

113

114

```typescript { .api }

115

/**

116

* Transforms decorator JSDoc

117

*/

118

function transformDecoratorJsdoc(): ts.TransformerFactory<ts.SourceFile>;

119

```

120

121

## Decorator Transformation Examples

122

123

### Class Decorators

124

125

```typescript

126

// Before transformation (TypeScript)

127

@Component({

128

selector: 'app-root',

129

templateUrl: './app.component.html'

130

})

131

export class AppComponent {

132

title = 'My App';

133

}

134

135

// After transformation (downleveled)

136

/** @nocollapse */

137

let AppComponent = class AppComponent {

138

constructor() {

139

this.title = 'My App';

140

}

141

};

142

AppComponent = __decorate([

143

Component({

144

selector: 'app-root',

145

templateUrl: './app.component.html'

146

})

147

], AppComponent);

148

exports.AppComponent = AppComponent;

149

```

150

151

### Method Decorators

152

153

```typescript

154

// Before transformation

155

class Service {

156

@cache()

157

getData(): Promise<Data> {

158

return fetch('/api/data');

159

}

160

}

161

162

// After transformation

163

class Service {

164

getData() {

165

return fetch('/api/data');

166

}

167

}

168

__decorate([

169

cache(),

170

__metadata("design:type", Function),

171

__metadata("design:paramtypes", []),

172

__metadata("design:returntype", Promise)

173

], Service.prototype, "getData", null);

174

```

175

176

### Property Decorators

177

178

```typescript

179

// Before transformation

180

class Model {

181

@observable

182

public value: string = '';

183

}

184

185

// After transformation

186

class Model {

187

constructor() {

188

this.value = '';

189

}

190

}

191

__decorate([

192

observable,

193

__metadata("design:type", String)

194

], Model.prototype, "value", void 0);

195

```

196

197

## Exporting Decorators

198

199

### @ExportDecoratedItems Pattern

200

201

Tsickle supports a special JSDoc annotation for decorators that should preserve their decorated items through Closure optimization:

202

203

```typescript

204

/**

205

* @ExportDecoratedItems

206

*/

207

function preserveExports(target: any) {

208

// Decorator implementation

209

}

210

211

@preserveExports

212

class ImportantClass {

213

// This class name will be preserved through optimization

214

}

215

```

216

217

The `@ExportDecoratedItems` annotation in the decorator's JSDoc tells tsickle to:

218

1. Add `@export` tags to decorated items

219

2. Preserve the original names through Closure compilation

220

3. Ensure the decorated items remain accessible after optimization

221

222

### Export Preservation

223

224

When a decorator is marked with `@ExportDecoratedItems`, tsickle automatically:

225

226

```typescript

227

// Original code

228

@preserveExports

229

class MyClass {}

230

231

// Generated output includes

232

/** @export */

233

class MyClass {}

234

```

235

236

## Integration with Other Systems

237

238

### Type System Integration

239

240

Decorator support integrates with the type translation system to:

241

- Preserve type information in decorator metadata

242

- Generate proper JSDoc for decorated members

243

- Handle generic decorators with type parameters

244

245

### Module System Integration

246

247

Decorator transformations work with the module system to:

248

- Properly import decorator functions in goog.module format

249

- Handle decorator dependencies across modules

250

- Ensure decorator metadata is available at runtime

251

252

### JSDoc Integration

253

254

Decorator processing coordinates with JSDoc generation to:

255

- Preserve existing JSDoc on decorated members

256

- Add required JSDoc annotations for Closure compatibility

257

- Handle decorator-specific JSDoc tags

258

259

## Configuration

260

261

Decorator behavior is controlled through the TsickleHost interface:

262

263

```typescript

264

interface TsickleHost {

265

/** Whether to downlevel decorators */

266

transformDecorators?: boolean;

267

// ... other options

268

}

269

270

// Usage

271

const host: TsickleHost = {

272

transformDecorators: true, // Enable decorator downleveling

273

transformTypesToClosure: true,

274

googmodule: true,

275

generateExtraSuppressions: true

276

};

277

```

278

279

## Runtime Requirements

280

281

For downleveled decorators to work correctly, the runtime environment must provide:

282

283

1. **__decorate function**: The decorator helper function

284

2. **__metadata function**: For design-time type metadata (when using reflect-metadata)

285

3. **Reflect.metadata**: If using reflection-based decorators

286

287

These are typically provided by:

288

- `tslib` for __decorate and __metadata

289

- `reflect-metadata` polyfill for Reflect.metadata

290

291

## Performance Considerations

292

293

Decorator processing is optimized for:

294

- **Selective downleveling**: Only downlevels decorators that need it

295

- **Metadata optimization**: Minimal metadata generation for better performance

296

- **Dead code elimination**: Unused decorators can be removed by Closure Compiler

297

- **Incremental compilation**: Only re-processes files with decorator changes