CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ramda

A practical functional library for JavaScript programmers.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

string-type.mddocs/

String & Type Functions

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.

String Functions

Case Conversion

// Convert to uppercase
R.toUpper('hello world');      // => 'HELLO WORLD'
R.toUpper('MiXeD cAsE');       // => 'MIXED CASE'

// Convert to lowercase  
R.toLower('HELLO WORLD');      // => 'hello world'
R.toLower('MiXeD cAsE');       // => 'mixed case'

// Curried usage for transformations
const normalizeNames = R.map(R.pipe(
  R.trim,
  R.toLower,
  R.replace(/\s+/g, ' ')       // Normalize whitespace
));

normalizeNames(['  ALICE  ', 'bob', '  CAROL SMITH  ']);
// => ['alice', 'bob', 'carol smith']

// Case-insensitive operations
const caseInsensitiveIncludes = R.pipe(
  R.juxt([R.toLower, R.pipe(R.nthArg(1), R.toLower)]),
  R.apply(R.includes)
);

const containsWord = R.curry((word, text) =>
  R.pipe(R.toLower, R.includes(R.toLower(word)))(text)
);

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

String Trimming

// Remove whitespace from both ends
R.trim('  hello world  ');    // => 'hello world'
R.trim('\n\t  text  \n\t');   // => 'text'
R.trim('no-spaces');          // => 'no-spaces'

// Clean up user input
const sanitizeInput = R.pipe(
  R.trim,
  R.replace(/\s+/g, ' '),      // Replace multiple spaces with single space
  R.when(R.isEmpty, R.always('(empty)'))
);

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

// Process form data
const cleanFormData = R.map(R.when(R.is(String), R.trim));
const formData = {
  name: '  John Doe  ',
  email: '  john@example.com  ',
  age: 30
};

cleanFormData(formData);
// => { name: 'John Doe', email: 'john@example.com', age: 30 }

String Splitting and Joining

// Split string by separator
R.split(' ', 'hello world foo');     // => ['hello', 'world', 'foo']
R.split(',', 'a,b,c,d');             // => ['a', 'b', 'c', 'd']
R.split('', 'hello');                // => ['h', 'e', 'l', 'l', 'o']

// Split by regex
R.split(/\s+/, 'hello   world\ttest'); // => ['hello', 'world', 'test']
R.split(/[,;]/, 'a,b;c,d');           // => ['a', 'b', 'c', 'd']

// Parse CSV-like data
const parseCSVRow = R.pipe(
  R.split(','),
  R.map(R.trim),
  R.reject(R.isEmpty)
);

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

// Path manipulation
const getPathSegments = R.pipe(
  R.split('/'),
  R.reject(R.isEmpty)
);

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

// Word processing
const getWords = R.pipe(
  R.toLower,
  R.split(/\W+/),
  R.reject(R.isEmpty)
);

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

String Replacement

// Replace substring or pattern
R.replace('foo', 'bar', 'foo foo foo');        // => 'bar foo foo' (first occurrence)
R.replace(/foo/g, 'bar', 'foo foo foo');       // => 'bar bar bar' (all occurrences)

// Template replacement
const template = 'Hello, {name}! Welcome to {site}.';
const replacePlaceholder = R.curry((key, value) => 
  R.replace(new RegExp(`\\{${key}\\}`, 'g'), value)
);

const personalizeMessage = R.pipe(
  replacePlaceholder('name', 'Alice'),
  replacePlaceholder('site', 'Our Platform')
);

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

// URL slug generation
const createSlug = R.pipe(
  R.toLower,
  R.trim,
  R.replace(/[^\w\s-]/g, ''),        // Remove special chars
  R.replace(/\s+/g, '-'),            // Replace spaces with hyphens
  R.replace(/-+/g, '-'),             // Replace multiple hyphens with single
  R.replace(/^-|-$/g, '')            // Remove leading/trailing hyphens
);

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

// Clean phone numbers
const cleanPhone = R.pipe(
  R.replace(/\D/g, ''),              // Remove non-digits
  R.replace(/^1/, ''),               // Remove country code
  R.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3') // Format
);

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

Pattern Matching

// Test if string matches pattern
R.test(/^\d+$/, '12345');           // => true (all digits)
R.test(/^\d+$/, '123a5');           // => false
R.test(/^[a-z]+$/i, 'Hello');       // => true (letters only, case-insensitive)

// Extract matches from string
R.match(/\d+/g, 'abc 123 def 456'); // => ['123', '456']
R.match(/(\w+)@(\w+)/, 'user@domain.com'); // => ['user@domain', 'user', 'domain']
R.match(/xyz/, 'abc');              // => [] (no matches)

// Validation functions
const isEmail = R.test(/^[\w\.-]+@[\w\.-]+\.\w+$/);
const isPhone = R.test(/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/);
const isZipCode = R.test(/^\d{5}(-\d{4})?$/);

isEmail('user@example.com');        // => true
isPhone('(555) 123-4567');          // => true
isZipCode('12345-6789');            // => true

// Extract information
const extractDomain = R.pipe(
  R.match(/@([\w.-]+)/),
  R.nth(1),
  R.defaultTo('unknown')
);

extractDomain('user@example.com');  // => 'example.com'
extractDomain('invalid-email');     // => 'unknown'

// Parse structured data
const parseLogEntry = R.pipe(
  R.match(/(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) \[(\w+)\] (.+)/),
  R.ifElse(
    R.isEmpty,
    R.always(null),
    ([, date, time, level, message]) => ({ date, time, level, message })
  )
);

parseLogEntry('2023-01-15 14:30:45 [ERROR] Database connection failed');
// => { date: '2023-01-15', time: '14:30:45', level: 'ERROR', message: 'Database connection failed' }

String Conversion and Representation

// Convert any value to string representation
R.toString(42);                     // => '42'
R.toString([1, 2, 3]);              // => '[1, 2, 3]'
R.toString({a: 1, b: 2});           // => '{"a": 1, "b": 2}'
R.toString(new Date('2023-01-15')); // => 'new Date("2023-01-15T00:00:00.000Z")'
R.toString(null);                   // => 'null'
R.toString(undefined);              // => 'undefined'

// Safe string conversion for display
const displayValue = R.pipe(
  R.when(R.isNil, R.always('N/A')),
  R.toString
);

displayValue(42);          // => '42'
displayValue(null);        // => 'N/A'
displayValue({id: 123});   // => '{"id": 123}'

// Format objects for logging
const formatForLog = R.pipe(
  R.toString,
  R.replace(/"/g, ''),       // Remove quotes for cleaner output
  R.replace(/,/g, ', ')      // Add spacing after commas
);

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

Type Functions

Type Detection

// Get type name as string
R.type(42);                    // => 'Number'
R.type('hello');               // => 'String'
R.type([1, 2, 3]);             // => 'Array'
R.type({a: 1});                // => 'Object'
R.type(null);                  // => 'Null'
R.type(undefined);             // => 'Undefined'
R.type(true);                  // => 'Boolean'
R.type(/regex/);               // => 'RegExp'
R.type(() => {});              // => 'Function'
R.type(async () => {});        // => 'AsyncFunction'
R.type(new Date());            // => 'Date'

// Type-based processing
const processValue = R.cond([
  [R.pipe(R.type, R.equals('Number')), R.multiply(2)],
  [R.pipe(R.type, R.equals('String')), R.toUpper],
  [R.pipe(R.type, R.equals('Array')), R.length],
  [R.T, R.always('Unknown type')]
]);

processValue(5);               // => 10
processValue('hello');         // => 'HELLO'  
processValue([1, 2, 3]);       // => 3
processValue(true);            // => 'Unknown type'

Instance and Constructor Checking

// Check if value is instance of constructor
R.is(Number, 42);              // => true
R.is(String, 'hello');         // => true
R.is(Array, [1, 2, 3]);        // => true
R.is(Object, {});              // => true
R.is(Date, new Date());        // => true
R.is(RegExp, /pattern/);       // => true

// Check inheritance chain
R.is(Object, []);              // => true (arrays inherit from Object)
R.is(Object, 'string');        // => false (primitives don't inherit)

// Custom constructor checking
function Person(name) { this.name = name; }
const john = new Person('John');

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

// Type guards for data validation
const isValidUser = R.where({
  id: R.is(Number),
  name: R.is(String),
  email: R.is(String),
  active: R.is(Boolean)
});

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

Null and Undefined Checking

// Check for null or undefined
R.isNil(null);                 // => true
R.isNil(undefined);            // => true
R.isNil(0);                    // => false
R.isNil(false);                // => false
R.isNil('');                   // => false
R.isNil([]);                   // => false

// Check for non-null and non-undefined
R.isNotNil(null);              // => false
R.isNotNil(undefined);         // => false  
R.isNotNil(0);                 // => true
R.isNotNil(false);             // => true
R.isNotNil('');                // => true

// Safe property access
const safeProp = R.curry((key, obj) => 
  R.when(R.isNotNil, R.prop(key))(obj)
);

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

// Filter out null/undefined values
const removeNils = R.filter(R.isNotNil);
removeNils([1, null, 2, undefined, 3]); // => [1, 2, 3]

// Provide defaults for nil values
const withDefaults = R.pipe(
  R.when(R.isNil, R.always({})),
  R.merge({name: 'Anonymous', age: 0})
);

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

Property Type Checking

// Check type of object property
R.propIs(Number, 'age', {age: 30});        // => true
R.propIs(String, 'name', {name: 'Alice'}); // => true
R.propIs(Array, 'tags', {tags: ['a', 'b']});  // => true
R.propIs(Number, 'missing', {});           // => false

// Validate object structure
const validateProduct = R.where({
  id: R.propIs(Number, 'id'),
  name: R.propIs(String, 'name'),
  price: R.propIs(Number, 'price'),
  tags: R.propIs(Array, 'tags')
});

const product = {
  id: 123,
  name: 'Widget',
  price: 29.99,
  tags: ['electronics', 'gadget']
};

validateProduct(product);          // => true

// Type-safe property extraction
const getNumberProp = R.curry((key, obj) =>
  R.when(R.propIs(Number, key), R.prop(key))(obj)
);

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

Advanced Type Operations

// Runtime type checking with detailed info
const analyzeValue = R.applySpec({
  value: R.identity,
  type: R.type,
  isNil: R.isNil,
  isNumber: R.is(Number),
  isString: R.is(String),
  isArray: R.is(Array),
  isEmpty: R.isEmpty
});

analyzeValue('hello');
// => {
//   value: 'hello',
//   type: 'String', 
//   isNil: false,
//   isNumber: false,
//   isString: true,
//   isArray: false,
//   isEmpty: false
// }

// Type-based routing
const routeByType = R.cond([
  [R.is(String), R.pipe(R.toUpper, R.concat('STRING: '))],
  [R.is(Number), R.pipe(R.multiply(2), R.toString, R.concat('NUMBER: '))],
  [R.is(Array), R.pipe(R.length, R.toString, R.concat('ARRAY LENGTH: '))],
  [R.T, R.pipe(R.type, R.concat('UNKNOWN TYPE: '))]
]);

routeByType('hello');          // => 'STRING: HELLO'
routeByType(42);               // => 'NUMBER: 84'
routeByType([1, 2, 3]);        // => 'ARRAY LENGTH: 3'
routeByType(true);             // => 'UNKNOWN TYPE: Boolean'

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

Install with Tessl CLI

npx tessl i tessl/npm-ramda

docs

function-functions.md

index.md

list-functions.md

math-logic.md

object-functions.md

string-type.md

tile.json