or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

function-functions.mdindex.mdlist-functions.mdmath-logic.mdobject-functions.mdstring-type.md

string-type.mddocs/

0

# String & Type Functions

1

2

Ramda provides 13 essential functions for string manipulation and type checking. This includes 8 string functions for text processing and 5 type functions for runtime type validation and inspection.

3

4

## String Functions

5

6

### Case Conversion

7

8

```javascript { .api }

9

// Convert to uppercase

10

R.toUpper('hello world'); // => 'HELLO WORLD'

11

R.toUpper('MiXeD cAsE'); // => 'MIXED CASE'

12

13

// Convert to lowercase

14

R.toLower('HELLO WORLD'); // => 'hello world'

15

R.toLower('MiXeD cAsE'); // => 'mixed case'

16

17

// Curried usage for transformations

18

const normalizeNames = R.map(R.pipe(

19

R.trim,

20

R.toLower,

21

R.replace(/\s+/g, ' ') // Normalize whitespace

22

));

23

24

normalizeNames([' ALICE ', 'bob', ' CAROL SMITH ']);

25

// => ['alice', 'bob', 'carol smith']

26

27

// Case-insensitive operations

28

const caseInsensitiveIncludes = R.pipe(

29

R.juxt([R.toLower, R.pipe(R.nthArg(1), R.toLower)]),

30

R.apply(R.includes)

31

);

32

33

const containsWord = R.curry((word, text) =>

34

R.pipe(R.toLower, R.includes(R.toLower(word)))(text)

35

);

36

37

containsWord('HELLO', 'hello world'); // => true

38

```

39

40

### String Trimming

41

42

```javascript { .api }

43

// Remove whitespace from both ends

44

R.trim(' hello world '); // => 'hello world'

45

R.trim('\n\t text \n\t'); // => 'text'

46

R.trim('no-spaces'); // => 'no-spaces'

47

48

// Clean up user input

49

const sanitizeInput = R.pipe(

50

R.trim,

51

R.replace(/\s+/g, ' '), // Replace multiple spaces with single space

52

R.when(R.isEmpty, R.always('(empty)'))

53

);

54

55

sanitizeInput(' hello world '); // => 'hello world'

56

sanitizeInput(' '); // => '(empty)'

57

58

// Process form data

59

const cleanFormData = R.map(R.when(R.is(String), R.trim));

60

const formData = {

61

name: ' John Doe ',

62

email: ' john@example.com ',

63

age: 30

64

};

65

66

cleanFormData(formData);

67

// => { name: 'John Doe', email: 'john@example.com', age: 30 }

68

```

69

70

### String Splitting and Joining

71

72

```javascript { .api }

73

// Split string by separator

74

R.split(' ', 'hello world foo'); // => ['hello', 'world', 'foo']

75

R.split(',', 'a,b,c,d'); // => ['a', 'b', 'c', 'd']

76

R.split('', 'hello'); // => ['h', 'e', 'l', 'l', 'o']

77

78

// Split by regex

79

R.split(/\s+/, 'hello world\ttest'); // => ['hello', 'world', 'test']

80

R.split(/[,;]/, 'a,b;c,d'); // => ['a', 'b', 'c', 'd']

81

82

// Parse CSV-like data

83

const parseCSVRow = R.pipe(

84

R.split(','),

85

R.map(R.trim),

86

R.reject(R.isEmpty)

87

);

88

89

parseCSVRow('name, age, city, '); // => ['name', 'age', 'city']

90

91

// Path manipulation

92

const getPathSegments = R.pipe(

93

R.split('/'),

94

R.reject(R.isEmpty)

95

);

96

97

getPathSegments('/users/123/profile'); // => ['users', '123', 'profile']

98

99

// Word processing

100

const getWords = R.pipe(

101

R.toLower,

102

R.split(/\W+/),

103

R.reject(R.isEmpty)

104

);

105

106

getWords('Hello, World! How are you?'); // => ['hello', 'world', 'how', 'are', 'you']

107

```

108

109

### String Replacement

110

111

```javascript { .api }

112

// Replace substring or pattern

113

R.replace('foo', 'bar', 'foo foo foo'); // => 'bar foo foo' (first occurrence)

114

R.replace(/foo/g, 'bar', 'foo foo foo'); // => 'bar bar bar' (all occurrences)

115

116

// Template replacement

117

const template = 'Hello, {name}! Welcome to {site}.';

118

const replacePlaceholder = R.curry((key, value) =>

119

R.replace(new RegExp(`\\{${key}\\}`, 'g'), value)

120

);

121

122

const personalizeMessage = R.pipe(

123

replacePlaceholder('name', 'Alice'),

124

replacePlaceholder('site', 'Our Platform')

125

);

126

127

personalizeMessage(template); // => 'Hello, Alice! Welcome to Our Platform.'

128

129

// URL slug generation

130

const createSlug = R.pipe(

131

R.toLower,

132

R.trim,

133

R.replace(/[^\w\s-]/g, ''), // Remove special chars

134

R.replace(/\s+/g, '-'), // Replace spaces with hyphens

135

R.replace(/-+/g, '-'), // Replace multiple hyphens with single

136

R.replace(/^-|-$/g, '') // Remove leading/trailing hyphens

137

);

138

139

createSlug(' Hello, World! This is a Test '); // => 'hello-world-this-is-a-test'

140

141

// Clean phone numbers

142

const cleanPhone = R.pipe(

143

R.replace(/\D/g, ''), // Remove non-digits

144

R.replace(/^1/, ''), // Remove country code

145

R.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3') // Format

146

);

147

148

cleanPhone('1-555-123-4567'); // => '(555) 123-4567'

149

```

150

151

### Pattern Matching

152

153

```javascript { .api }

154

// Test if string matches pattern

155

R.test(/^\d+$/, '12345'); // => true (all digits)

156

R.test(/^\d+$/, '123a5'); // => false

157

R.test(/^[a-z]+$/i, 'Hello'); // => true (letters only, case-insensitive)

158

159

// Extract matches from string

160

R.match(/\d+/g, 'abc 123 def 456'); // => ['123', '456']

161

R.match(/(\w+)@(\w+)/, 'user@domain.com'); // => ['user@domain', 'user', 'domain']

162

R.match(/xyz/, 'abc'); // => [] (no matches)

163

164

// Validation functions

165

const isEmail = R.test(/^[\w\.-]+@[\w\.-]+\.\w+$/);

166

const isPhone = R.test(/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/);

167

const isZipCode = R.test(/^\d{5}(-\d{4})?$/);

168

169

isEmail('user@example.com'); // => true

170

isPhone('(555) 123-4567'); // => true

171

isZipCode('12345-6789'); // => true

172

173

// Extract information

174

const extractDomain = R.pipe(

175

R.match(/@([\w.-]+)/),

176

R.nth(1),

177

R.defaultTo('unknown')

178

);

179

180

extractDomain('user@example.com'); // => 'example.com'

181

extractDomain('invalid-email'); // => 'unknown'

182

183

// Parse structured data

184

const parseLogEntry = R.pipe(

185

R.match(/(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) \[(\w+)\] (.+)/),

186

R.ifElse(

187

R.isEmpty,

188

R.always(null),

189

([, date, time, level, message]) => ({ date, time, level, message })

190

)

191

);

192

193

parseLogEntry('2023-01-15 14:30:45 [ERROR] Database connection failed');

194

// => { date: '2023-01-15', time: '14:30:45', level: 'ERROR', message: 'Database connection failed' }

195

```

196

197

### String Conversion and Representation

198

199

```javascript { .api }

200

// Convert any value to string representation

201

R.toString(42); // => '42'

202

R.toString([1, 2, 3]); // => '[1, 2, 3]'

203

R.toString({a: 1, b: 2}); // => '{"a": 1, "b": 2}'

204

R.toString(new Date('2023-01-15')); // => 'new Date("2023-01-15T00:00:00.000Z")'

205

R.toString(null); // => 'null'

206

R.toString(undefined); // => 'undefined'

207

208

// Safe string conversion for display

209

const displayValue = R.pipe(

210

R.when(R.isNil, R.always('N/A')),

211

R.toString

212

);

213

214

displayValue(42); // => '42'

215

displayValue(null); // => 'N/A'

216

displayValue({id: 123}); // => '{"id": 123}'

217

218

// Format objects for logging

219

const formatForLog = R.pipe(

220

R.toString,

221

R.replace(/"/g, ''), // Remove quotes for cleaner output

222

R.replace(/,/g, ', ') // Add spacing after commas

223

);

224

225

formatForLog({user: 'alice', action: 'login'});

226

// => '{user: alice, action: login}'

227

```

228

229

## Type Functions

230

231

### Type Detection

232

233

```javascript { .api }

234

// Get type name as string

235

R.type(42); // => 'Number'

236

R.type('hello'); // => 'String'

237

R.type([1, 2, 3]); // => 'Array'

238

R.type({a: 1}); // => 'Object'

239

R.type(null); // => 'Null'

240

R.type(undefined); // => 'Undefined'

241

R.type(true); // => 'Boolean'

242

R.type(/regex/); // => 'RegExp'

243

R.type(() => {}); // => 'Function'

244

R.type(async () => {}); // => 'AsyncFunction'

245

R.type(new Date()); // => 'Date'

246

247

// Type-based processing

248

const processValue = R.cond([

249

[R.pipe(R.type, R.equals('Number')), R.multiply(2)],

250

[R.pipe(R.type, R.equals('String')), R.toUpper],

251

[R.pipe(R.type, R.equals('Array')), R.length],

252

[R.T, R.always('Unknown type')]

253

]);

254

255

processValue(5); // => 10

256

processValue('hello'); // => 'HELLO'

257

processValue([1, 2, 3]); // => 3

258

processValue(true); // => 'Unknown type'

259

```

260

261

### Instance and Constructor Checking

262

263

```javascript { .api }

264

// Check if value is instance of constructor

265

R.is(Number, 42); // => true

266

R.is(String, 'hello'); // => true

267

R.is(Array, [1, 2, 3]); // => true

268

R.is(Object, {}); // => true

269

R.is(Date, new Date()); // => true

270

R.is(RegExp, /pattern/); // => true

271

272

// Check inheritance chain

273

R.is(Object, []); // => true (arrays inherit from Object)

274

R.is(Object, 'string'); // => false (primitives don't inherit)

275

276

// Custom constructor checking

277

function Person(name) { this.name = name; }

278

const john = new Person('John');

279

280

R.is(Person, john); // => true

281

R.is(Object, john); // => true

282

283

// Type guards for data validation

284

const isValidUser = R.where({

285

id: R.is(Number),

286

name: R.is(String),

287

email: R.is(String),

288

active: R.is(Boolean)

289

});

290

291

const user = { id: 123, name: 'Alice', email: 'alice@example.com', active: true };

292

isValidUser(user); // => true

293

```

294

295

### Null and Undefined Checking

296

297

```javascript { .api }

298

// Check for null or undefined

299

R.isNil(null); // => true

300

R.isNil(undefined); // => true

301

R.isNil(0); // => false

302

R.isNil(false); // => false

303

R.isNil(''); // => false

304

R.isNil([]); // => false

305

306

// Check for non-null and non-undefined

307

R.isNotNil(null); // => false

308

R.isNotNil(undefined); // => false

309

R.isNotNil(0); // => true

310

R.isNotNil(false); // => true

311

R.isNotNil(''); // => true

312

313

// Safe property access

314

const safeProp = R.curry((key, obj) =>

315

R.when(R.isNotNil, R.prop(key))(obj)

316

);

317

318

safeProp('name', {name: 'Alice'}); // => 'Alice'

319

safeProp('name', null); // => null

320

safeProp('name', undefined); // => undefined

321

322

// Filter out null/undefined values

323

const removeNils = R.filter(R.isNotNil);

324

removeNils([1, null, 2, undefined, 3]); // => [1, 2, 3]

325

326

// Provide defaults for nil values

327

const withDefaults = R.pipe(

328

R.when(R.isNil, R.always({})),

329

R.merge({name: 'Anonymous', age: 0})

330

);

331

332

withDefaults({name: 'Alice'}); // => {name: 'Alice', age: 0}

333

withDefaults(null); // => {name: 'Anonymous', age: 0}

334

```

335

336

### Property Type Checking

337

338

```javascript { .api }

339

// Check type of object property

340

R.propIs(Number, 'age', {age: 30}); // => true

341

R.propIs(String, 'name', {name: 'Alice'}); // => true

342

R.propIs(Array, 'tags', {tags: ['a', 'b']}); // => true

343

R.propIs(Number, 'missing', {}); // => false

344

345

// Validate object structure

346

const validateProduct = R.where({

347

id: R.propIs(Number, 'id'),

348

name: R.propIs(String, 'name'),

349

price: R.propIs(Number, 'price'),

350

tags: R.propIs(Array, 'tags')

351

});

352

353

const product = {

354

id: 123,

355

name: 'Widget',

356

price: 29.99,

357

tags: ['electronics', 'gadget']

358

};

359

360

validateProduct(product); // => true

361

362

// Type-safe property extraction

363

const getNumberProp = R.curry((key, obj) =>

364

R.when(R.propIs(Number, key), R.prop(key))(obj)

365

);

366

367

getNumberProp('age', {age: 30}); // => 30

368

getNumberProp('age', {age: 'thirty'}); // => {age: 'thirty'} (unchanged)

369

```

370

371

### Advanced Type Operations

372

373

```javascript { .api }

374

// Runtime type checking with detailed info

375

const analyzeValue = R.applySpec({

376

value: R.identity,

377

type: R.type,

378

isNil: R.isNil,

379

isNumber: R.is(Number),

380

isString: R.is(String),

381

isArray: R.is(Array),

382

isEmpty: R.isEmpty

383

});

384

385

analyzeValue('hello');

386

// => {

387

// value: 'hello',

388

// type: 'String',

389

// isNil: false,

390

// isNumber: false,

391

// isString: true,

392

// isArray: false,

393

// isEmpty: false

394

// }

395

396

// Type-based routing

397

const routeByType = R.cond([

398

[R.is(String), R.pipe(R.toUpper, R.concat('STRING: '))],

399

[R.is(Number), R.pipe(R.multiply(2), R.toString, R.concat('NUMBER: '))],

400

[R.is(Array), R.pipe(R.length, R.toString, R.concat('ARRAY LENGTH: '))],

401

[R.T, R.pipe(R.type, R.concat('UNKNOWN TYPE: '))]

402

]);

403

404

routeByType('hello'); // => 'STRING: HELLO'

405

routeByType(42); // => 'NUMBER: 84'

406

routeByType([1, 2, 3]); // => 'ARRAY LENGTH: 3'

407

routeByType(true); // => 'UNKNOWN TYPE: Boolean'

408

```

409

410

These string and type functions provide essential utilities for text processing, data validation, and runtime type safety in functional JavaScript applications.