or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdnode-constructors.mdnode-manipulation.mdparser-processor.mdtype-guards.md

type-guards.mddocs/

0

# Type Guards

1

2

Runtime type checking functions for identifying and validating AST node types. Essential for safely working with the parsed AST and implementing type-specific logic.

3

4

## Capabilities

5

6

### General Node Validation

7

8

Core functions for validating nodes and their capabilities.

9

10

```javascript { .api }

11

/**

12

* Check if value is a valid AST node

13

* @param node - Value to check

14

* @returns True if value is a node

15

*/

16

function isNode(node: any): boolean;

17

18

/**

19

* Check if node is a container (can have children)

20

* @param node - Node to check

21

* @returns True if node is Root, Selector, or Pseudo

22

*/

23

function isContainer(node: any): boolean;

24

25

/**

26

* Check if node supports namespaces

27

* @param node - Node to check

28

* @returns True if node is Attribute or Tag

29

*/

30

function isNamespace(node: any): boolean;

31

```

32

33

**Usage Examples:**

34

35

```javascript

36

const parser = require('postcss-selector-parser');

37

38

const ast = parser().astSync('.class, #id');

39

const node = ast.first.first;

40

41

// Check if it's a valid node

42

if (parser.isNode(node)) {

43

console.log('Valid node:', node.type);

44

}

45

46

// Check if it can contain children

47

if (parser.isContainer(node)) {

48

console.log('Can contain children');

49

node.walk(child => {

50

console.log('Child:', child.type);

51

});

52

}

53

54

// Check if it supports namespaces

55

if (parser.isNamespace(node)) {

56

console.log('Supports namespaces');

57

console.log('Namespace:', node.namespace);

58

}

59

```

60

61

### Container Type Guards

62

63

Functions for identifying specific container node types.

64

65

```javascript { .api }

66

/**

67

* Check if node is a Root container

68

* @param node - Node to check

69

* @returns True if node is Root

70

*/

71

function isRoot(node: any): boolean;

72

73

/**

74

* Check if node is a Selector container

75

* @param node - Node to check

76

* @returns True if node is Selector

77

*/

78

function isSelector(node: any): boolean;

79

80

/**

81

* Check if node is a Pseudo container

82

* @param node - Node to check

83

* @returns True if node is Pseudo

84

*/

85

function isPseudo(node: any): boolean;

86

```

87

88

**Usage Examples:**

89

90

```javascript

91

const parser = require('postcss-selector-parser');

92

93

const ast = parser().astSync('.class:hover');

94

95

// Check root

96

if (parser.isRoot(ast)) {

97

console.log('This is the root container');

98

console.log('Selectors:', ast.nodes.length);

99

}

100

101

// Check selector

102

const firstChild = ast.first;

103

if (parser.isSelector(firstChild)) {

104

console.log('This is a selector');

105

console.log('Components:', firstChild.nodes.length);

106

}

107

108

// Check pseudo

109

const pseudo = firstChild.last;

110

if (parser.isPseudo(pseudo)) {

111

console.log('This is a pseudo selector');

112

console.log('Value:', pseudo.value);

113

}

114

```

115

116

### Leaf Node Type Guards

117

118

Functions for identifying specific leaf node types that cannot contain children.

119

120

```javascript { .api }

121

/**

122

* Check if node is an Attribute selector

123

* @param node - Node to check

124

* @returns True if node is Attribute

125

*/

126

function isAttribute(node: any): boolean;

127

128

/**

129

* Check if node is a ClassName selector

130

* @param node - Node to check

131

* @returns True if node is ClassName

132

*/

133

function isClassName(node: any): boolean;

134

135

/**

136

* Check if node is a Combinator

137

* @param node - Node to check

138

* @returns True if node is Combinator

139

*/

140

function isCombinator(node: any): boolean;

141

142

/**

143

* Check if node is a Comment

144

* @param node - Node to check

145

* @returns True if node is Comment

146

*/

147

function isComment(node: any): boolean;

148

149

/**

150

* Check if node is an Identifier (ID selector)

151

* @param node - Node to check

152

* @returns True if node is Identifier

153

*/

154

function isIdentifier(node: any): boolean;

155

156

/**

157

* Check if node is a Nesting selector

158

* @param node - Node to check

159

* @returns True if node is Nesting

160

*/

161

function isNesting(node: any): boolean;

162

163

/**

164

* Check if node is a String literal

165

* @param node - Node to check

166

* @returns True if node is String

167

*/

168

function isString(node: any): boolean;

169

170

/**

171

* Check if node is a Tag selector

172

* @param node - Node to check

173

* @returns True if node is Tag

174

*/

175

function isTag(node: any): boolean;

176

177

/**

178

* Check if node is a Universal selector

179

* @param node - Node to check

180

* @returns True if node is Universal

181

*/

182

function isUniversal(node: any): boolean;

183

```

184

185

**Usage Examples:**

186

187

```javascript

188

const parser = require('postcss-selector-parser');

189

190

const ast = parser().astSync('div.class#id[href] > * + /* comment */');

191

const selector = ast.first;

192

193

// Walk through nodes and identify types

194

selector.walk(node => {

195

if (parser.isTag(node)) {

196

console.log('Tag:', node.value);

197

} else if (parser.isClassName(node)) {

198

console.log('Class:', node.value);

199

} else if (parser.isIdentifier(node)) {

200

console.log('ID:', node.value);

201

} else if (parser.isAttribute(node)) {

202

console.log('Attribute:', node.attribute);

203

} else if (parser.isCombinator(node)) {

204

console.log('Combinator:', node.value);

205

} else if (parser.isUniversal(node)) {

206

console.log('Universal selector');

207

} else if (parser.isComment(node)) {

208

console.log('Comment:', node.value);

209

}

210

});

211

```

212

213

### Pseudo Type Guards

214

215

Specialized functions for distinguishing between pseudo-classes and pseudo-elements.

216

217

```javascript { .api }

218

/**

219

* Check if node is specifically a pseudo-element

220

* @param node - Node to check

221

* @returns True if node is a pseudo-element

222

*/

223

function isPseudoElement(node: any): boolean;

224

225

/**

226

* Check if node is specifically a pseudo-class

227

* @param node - Node to check

228

* @returns True if node is a pseudo-class

229

*/

230

function isPseudoClass(node: any): boolean;

231

```

232

233

**Usage Examples:**

234

235

```javascript

236

const parser = require('postcss-selector-parser');

237

238

const ast = parser().astSync('.btn:hover::before:first-letter');

239

const selector = ast.first;

240

241

selector.walkPseudos(pseudo => {

242

if (parser.isPseudoElement(pseudo)) {

243

console.log('Pseudo-element:', pseudo.value);

244

// Outputs: ::before, :first-letter

245

} else if (parser.isPseudoClass(pseudo)) {

246

console.log('Pseudo-class:', pseudo.value);

247

// Outputs: :hover

248

}

249

});

250

251

// Specific pseudo-element detection

252

const pseudos = [':before', ':after', '::before', '::after', ':first-letter', ':first-line'];

253

pseudos.forEach(pseudoValue => {

254

const node = parser.pseudo({ value: pseudoValue });

255

console.log(`${pseudoValue} is pseudo-element:`, parser.isPseudoElement(node));

256

});

257

```

258

259

### Type-Safe Processing

260

261

Using type guards for safe node processing and transformation.

262

263

**Usage Examples:**

264

265

```javascript

266

const parser = require('postcss-selector-parser');

267

268

// Transform function using type guards

269

const transform = selectors => {

270

selectors.walk(node => {

271

// Remove universal selectors

272

if (parser.isUniversal(node)) {

273

node.remove();

274

return;

275

}

276

277

// Convert all IDs to classes

278

if (parser.isIdentifier(node)) {

279

const className = parser.className({ value: node.value });

280

node.replaceWith(className);

281

return;

282

}

283

284

// Add namespace to tags

285

if (parser.isTag(node)) {

286

node.namespace = 'app';

287

return;

288

}

289

290

// Process attributes

291

if (parser.isAttribute(node)) {

292

if (node.attribute === 'class') {

293

// Convert [class="value"] to .value

294

if (node.operator === '=' && node.value) {

295

const className = parser.className({ value: node.value });

296

node.replaceWith(className);

297

}

298

}

299

return;

300

}

301

});

302

};

303

304

const processor = parser(transform);

305

const result = processor.processSync('*#header.nav[class="btn"]');

306

// Result: app|#header.nav.btn

307

```

308

309

### Advanced Type Guard Usage

310

311

Combining type guards for complex logic and validation.

312

313

**Usage Examples:**

314

315

```javascript

316

const parser = require('postcss-selector-parser');

317

318

// Function to analyze selector complexity

319

function analyzeSelector(selectorString) {

320

const ast = parser().astSync(selectorString);

321

const stats = {

322

selectors: 0,

323

tags: 0,

324

classes: 0,

325

ids: 0,

326

attributes: 0,

327

pseudoClasses: 0,

328

pseudoElements: 0,

329

combinators: 0,

330

hasNamespaces: false,

331

hasComments: false

332

};

333

334

ast.walk(node => {

335

if (parser.isSelector(node)) {

336

stats.selectors++;

337

} else if (parser.isTag(node)) {

338

stats.tags++;

339

if (parser.isNamespace(node) && node.namespace) {

340

stats.hasNamespaces = true;

341

}

342

} else if (parser.isClassName(node)) {

343

stats.classes++;

344

} else if (parser.isIdentifier(node)) {

345

stats.ids++;

346

} else if (parser.isAttribute(node)) {

347

stats.attributes++;

348

} else if (parser.isPseudoClass(node)) {

349

stats.pseudoClasses++;

350

} else if (parser.isPseudoElement(node)) {

351

stats.pseudoElements++;

352

} else if (parser.isCombinator(node)) {

353

stats.combinators++;

354

} else if (parser.isComment(node)) {

355

stats.hasComments = true;

356

}

357

});

358

359

return stats;

360

}

361

362

// Usage

363

const stats = analyzeSelector('div.nav#main[data-id] > .item:hover::before');

364

console.log(stats);

365

// { selectors: 1, tags: 1, classes: 2, ids: 1, attributes: 1,

366

// pseudoClasses: 1, pseudoElements: 1, combinators: 1, ... }

367

```