or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdasync.mdcollections.mdindex.mdnumbers.mdobjects.mdprimitives.mdstrings.mdtyped-arrays.mdvalidation.mdweb-apis.md

strings.mddocs/

0

# Strings and Text

1

2

String-specific validation including empty strings, whitespace detection, numeric strings, URL strings, and text content validation.

3

4

## Capabilities

5

6

### String Emptiness Checking

7

8

Check if strings are empty or contain only whitespace.

9

10

```typescript { .api }

11

/**

12

* Check if value is an empty string

13

* @param value - Value to check

14

* @returns True if value is empty string

15

*/

16

function isEmptyString(value: unknown): value is '';

17

18

/**

19

* Check if value is empty string or contains only whitespace

20

* @param value - Value to check

21

* @returns True if value is empty or whitespace string

22

*/

23

function isEmptyStringOrWhitespace(value: unknown): value is '' | Whitespace;

24

25

type Whitespace = ' '; // Represents whitespace-only strings

26

```

27

28

**Usage Examples:**

29

30

```typescript

31

import is from '@sindresorhus/is';

32

33

is.emptyString(''); // => true

34

is.emptyString('hello'); // => false

35

is.emptyString(null); // => false

36

37

is.emptyStringOrWhitespace(''); // => true

38

is.emptyStringOrWhitespace(' '); // => true

39

is.emptyStringOrWhitespace('\t\n'); // => true

40

is.emptyStringOrWhitespace('hello'); // => false

41

42

// Type guard usage

43

function processInput(input: unknown) {

44

if (is.string(input) && !is.emptyStringOrWhitespace(input)) {

45

// input is now typed as non-empty string

46

return input.trim().toUpperCase();

47

}

48

throw new Error('Input must be a non-empty string');

49

}

50

```

51

52

### Non-empty String Checking

53

54

Check if strings contain content or meaningful text.

55

56

```typescript { .api }

57

/**

58

* Check if value is a non-empty string

59

* @param value - Value to check

60

* @returns True if value is non-empty string

61

*/

62

function isNonEmptyString(value: unknown): value is NonEmptyString;

63

64

/**

65

* Check if value is non-empty string and not just whitespace

66

* @param value - Value to check

67

* @returns True if value is non-empty string with content

68

*/

69

function isNonEmptyStringAndNotWhitespace(value: unknown): value is NonEmptyString;

70

71

type NonEmptyString = string & {0: string}; // String with at least one character

72

```

73

74

**Usage Examples:**

75

76

```typescript

77

import is from '@sindresorhus/is';

78

79

is.nonEmptyString('hello'); // => true

80

is.nonEmptyString(' '); // => true (has characters, even if whitespace)

81

is.nonEmptyString(''); // => false

82

83

is.nonEmptyStringAndNotWhitespace('hello'); // => true

84

is.nonEmptyStringAndNotWhitespace('hello world'); // => true

85

is.nonEmptyStringAndNotWhitespace(' '); // => false

86

is.nonEmptyStringAndNotWhitespace(''); // => false

87

88

// Filtering arrays

89

const values = ['property1', '', null, 'property2', ' ', undefined];

90

const validStrings = values.filter(is.nonEmptyStringAndNotWhitespace);

91

console.log(validStrings); // ['property1', 'property2']

92

93

// Type guard usage

94

function createSlug(title: unknown) {

95

if (is.nonEmptyStringAndNotWhitespace(title)) {

96

// title is now typed as NonEmptyString with guaranteed content

97

return title.toLowerCase().replace(/\s+/g, '-');

98

}

99

throw new Error('Title must be a non-empty string with content');

100

}

101

```

102

103

### Whitespace String Checking

104

105

Check if a string contains only whitespace characters.

106

107

```typescript { .api }

108

/**

109

* Check if value is a string containing only whitespace

110

* @param value - Value to check

111

* @returns True if value is whitespace-only string

112

*/

113

function isWhitespaceString(value: unknown): value is Whitespace;

114

```

115

116

**Usage Examples:**

117

118

```typescript

119

import is from '@sindresorhus/is';

120

121

is.whitespaceString(' '); // => true

122

is.whitespaceString('\t\n\r '); // => true

123

is.whitespaceString(''); // => false (empty, not whitespace)

124

is.whitespaceString('hello'); // => false

125

is.whitespaceString(' hello '); // => false (contains non-whitespace)

126

127

// Type guard usage

128

function normalizeText(text: unknown) {

129

if (is.string(text)) {

130

if (is.whitespaceString(text)) {

131

return ''; // Convert whitespace-only to empty

132

}

133

return text.trim();

134

}

135

return null;

136

}

137

```

138

139

### Numeric String Validation

140

141

Check if a string represents a valid number.

142

143

```typescript { .api }

144

/**

145

* Check if string represents a valid number

146

* @param value - Value to check

147

* @returns True if value is numeric string

148

*/

149

function isNumericString(value: unknown): value is `${number}`;

150

```

151

152

**Usage Examples:**

153

154

```typescript

155

import is from '@sindresorhus/is';

156

157

is.numericString('42'); // => true

158

is.numericString('3.14'); // => true

159

is.numericString('-123'); // => true

160

is.numericString('1e10'); // => true

161

is.numericString('Infinity'); // => true

162

is.numericString('-Infinity'); // => true

163

164

is.numericString('NaN'); // => false

165

is.numericString('42px'); // => false

166

is.numericString(''); // => false

167

is.numericString(' '); // => false

168

169

// Type guard usage

170

function parseUserInput(input: unknown) {

171

if (is.string(input) && is.numericString(input)) {

172

// input is typed as `${number}`

173

return Number(input);

174

}

175

return null;

176

}

177

178

// Form validation

179

function validateNumberField(field: unknown) {

180

if (is.nonEmptyStringAndNotWhitespace(field) && is.numericString(field)) {

181

const num = Number(field);

182

return { valid: true, value: num };

183

}

184

return { valid: false, error: 'Must be a valid number' };

185

}

186

```

187

188

### URL String Validation

189

190

Check if a string is a valid URL.

191

192

```typescript { .api }

193

/**

194

* Check if string is a valid URL

195

* @param value - Value to check

196

* @returns True if value is valid URL string

197

*/

198

function isUrlString(value: unknown): value is string;

199

```

200

201

**Usage Examples:**

202

203

```typescript

204

import is from '@sindresorhus/is';

205

206

is.urlString('https://example.com'); // => true

207

is.urlString('http://localhost:3000'); // => true

208

is.urlString('ftp://files.example.com'); // => true

209

is.urlString('mailto:user@example.com'); // => true

210

211

is.urlString('example.com'); // => false (no protocol)

212

is.urlString('https://'); // => false (incomplete)

213

is.urlString('not a url'); // => false

214

215

// Type guard usage

216

function openUrl(url: unknown) {

217

if (is.urlString(url)) {

218

// url is now typed as string and guaranteed to be valid URL

219

window.open(url, '_blank');

220

} else {

221

throw new Error('Invalid URL provided');

222

}

223

}

224

225

// URL validation with additional checks

226

function validateWebUrl(url: unknown) {

227

if (is.urlString(url)) {

228

const urlObj = new URL(url);

229

if (urlObj.protocol === 'https:' || urlObj.protocol === 'http:') {

230

return urlObj;

231

}

232

throw new Error('Only HTTP and HTTPS URLs are allowed');

233

}

234

throw new Error('Invalid URL format');

235

}

236

```

237

238

## Usage Patterns

239

240

### Form Field Validation

241

242

```typescript

243

import is from '@sindresorhus/is';

244

245

interface FormData {

246

name: string;

247

email: string;

248

age: number;

249

website?: string;

250

}

251

252

function validateForm(data: Record<string, unknown>): FormData {

253

const errors: string[] = [];

254

255

// Name validation

256

if (!is.nonEmptyStringAndNotWhitespace(data.name)) {

257

errors.push('Name is required and cannot be empty');

258

}

259

260

// Email validation (basic)

261

if (!is.nonEmptyStringAndNotWhitespace(data.email) || !data.email.includes('@')) {

262

errors.push('Valid email is required');

263

}

264

265

// Age validation

266

let age: number;

267

if (is.numericString(data.age)) {

268

age = Number(data.age);

269

} else if (is.number(data.age)) {

270

age = data.age;

271

} else {

272

errors.push('Age must be a number');

273

}

274

275

// Website validation (optional)

276

let website: string | undefined;

277

if (data.website !== undefined && data.website !== '') {

278

if (is.urlString(data.website)) {

279

website = data.website;

280

} else {

281

errors.push('Website must be a valid URL');

282

}

283

}

284

285

if (errors.length > 0) {

286

throw new Error(errors.join(', '));

287

}

288

289

return {

290

name: data.name as string,

291

email: data.email as string,

292

age: age!,

293

website

294

};

295

}

296

```

297

298

### Text Processing

299

300

```typescript

301

import is from '@sindresorhus/is';

302

303

function cleanTextArray(texts: unknown[]): string[] {

304

return texts

305

.filter(is.string) // Only strings

306

.filter(is.nonEmptyStringAndNotWhitespace) // With content

307

.map(text => text.trim()) // Clean whitespace

308

.filter((text, index, array) => array.indexOf(text) === index); // Remove duplicates

309

}

310

311

function processUserInput(input: unknown): string | null {

312

if (!is.string(input)) {

313

return null;

314

}

315

316

if (is.emptyStringOrWhitespace(input)) {

317

return null;

318

}

319

320

// Clean and normalize

321

return input.trim().replace(/\s+/g, ' ');

322

}

323

```

324

325

### Configuration Validation

326

327

```typescript

328

import is from '@sindresorhus/is';

329

330

interface Config {

331

apiUrl: string;

332

timeout: number;

333

retries: number;

334

debug: boolean;

335

}

336

337

function validateConfig(config: Record<string, unknown>): Config {

338

// API URL validation

339

if (!is.urlString(config.apiUrl)) {

340

throw new Error('apiUrl must be a valid URL');

341

}

342

343

// Timeout validation

344

let timeout: number;

345

if (is.numericString(config.timeout)) {

346

timeout = Number(config.timeout);

347

} else if (is.number(config.timeout)) {

348

timeout = config.timeout;

349

} else {

350

throw new Error('timeout must be a number');

351

}

352

353

// Retries validation

354

let retries: number;

355

if (is.numericString(config.retries)) {

356

retries = Number(config.retries);

357

} else if (is.number(config.retries)) {

358

retries = config.retries;

359

} else {

360

throw new Error('retries must be a number');

361

}

362

363

// Debug flag

364

let debug: boolean;

365

if (is.boolean(config.debug)) {

366

debug = config.debug;

367

} else if (is.string(config.debug)) {

368

debug = config.debug.toLowerCase() === 'true';

369

} else {

370

debug = false;

371

}

372

373

return {

374

apiUrl: config.apiUrl,

375

timeout,

376

retries,

377

debug

378

};

379

}

380

```

381

382

### Search and Filter

383

384

```typescript

385

import is from '@sindresorhus/is';

386

387

function searchItems(items: unknown[], query: unknown): string[] {

388

if (!is.nonEmptyStringAndNotWhitespace(query)) {

389

return [];

390

}

391

392

const searchTerm = query.toLowerCase();

393

394

return items

395

.filter(is.string)

396

.filter(item => item.toLowerCase().includes(searchTerm));

397

}

398

399

function filterValidUrls(urls: unknown[]): string[] {

400

return urls.filter(is.urlString);

401

}

402

```

403

404

## Notes

405

406

- Empty string checking distinguishes between `''` and whitespace-only strings

407

- `isNonEmptyString()` includes whitespace-only strings; use `isNonEmptyStringAndNotWhitespace()` to exclude them

408

- Whitespace detection includes spaces, tabs, newlines, and other whitespace characters

409

- Numeric string validation excludes `'NaN'` but includes `'Infinity'` and `'-Infinity'`

410

- URL validation uses the `URL` constructor internally for accurate validation

411

- URL validation supports all valid URL schemes (http, https, ftp, mailto, etc.)

412

- All string checks work with TypeScript type guards for compile-time type narrowing

413

- `NonEmptyString` type ensures string has at least one character at compile time