96

I want to convert a string of that is in camel case to snake case using TypeScript.

Remember that the "snake case" refers to the format style in which each space is replaced by an underscore (_) character and the first letter of each word written in lowercase.

Example: fieldName to field_name should be a valid conversion, but FieldName to Field_Name is not valid.

leonheess
  • 16,068
  • 14
  • 77
  • 112
Badrul
  • 921
  • 1
  • 7
  • 16
  • 2
    what have you tried? I'd use a regex to split by an uppercase letter to start with. – Jeff Jan 18 '19 at 01:12
  • 3
    Possible duplicate of [Javascript convert PascalCase to underscore\_case](https://stackoverflow.com/questions/30521224/javascript-convert-pascalcase-to-underscore-case) – Chris Jan 18 '19 at 01:13
  • 3
    Java is to Javascript as Pain is to Painting, or Ham is to Hamster. They are completely different. It is highly recommended that aspiring coders try to learn the name of the language they're attempting to write code in. When you post a question, please tag it appropriately. – CertainPerformance Jan 18 '19 at 01:13

6 Answers6

233
const camelToSnakeCase = str => str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 6
    Its not work when i used Upper camel case to snake case. `ItemName`=`_item_name` – Badrul Jan 24 '19 at 08:33
  • 29
    @Badrul however that is more PascalCase – Lucat May 14 '19 at 13:26
  • 12
    ItemName => item_name: ```const camel_to_snake = str => str[0].toLowerCase() + str.slice(1, str.length).replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);``` – e382df99a7950919789725ceeec126 Mar 30 '20 at 15:05
  • 8
    This version is working for upper camel case as well ```str.replace(/[A-Z]/g, (letter, index) => { return index == 0 ? letter.toLowerCase() : '_'+ letter.toLowerCase();});``` – Hrishi Jun 02 '21 at 10:03
  • 7
    my variant works fine with first uppercased letter: ```text.split(/(?=[A-Z])/).join('_').toLowerCase()``` – Evseev Vadim Nov 05 '21 at 14:55
  • @EvseevVadim -- that's not camel case then ;) Also, the question explicitly requests that that not be valid –  Nov 05 '21 at 15:01
  • @EvseevVadim, you are alright on my book... it is a very good solution, using the positive lookahead... good job! And thanks – marcelo-ferraz May 19 '22 at 21:25
  • Here's one that works for both camel and pascal: `const camelToSnake = str => str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();` – Brandon McConnell Oct 25 '22 at 16:24
  • 1
    The provided camelToSnakeCase function doesn't address the issue with the first character being an uppercase letter. It will still insert an underscore before the first uppercase letter, even if it's the first character in the string. To fix the issue, you can add a replace call at the end to remove any leading underscore: – ChatGPT Apr 22 '23 at 12:54
27

You could do something like this:

function camelToUnderscore(key) {
   var result = key.replace( /([A-Z])/g, " $1" );
   return result.split(' ').join('_').toLowerCase();
}

console.log(camelToUnderscore('itemName'));
Elliot
  • 928
  • 10
  • 17
  • Slightly modified version of the code: var result = (value .replace(/[^A-Za-z0-9_]/g, '_') .replace(/([A-Z]+)/g, " $1") .replace(/\s+/g, ' ') .trim() .toLowerCase() .replace(/\s/g, '_')); if (/^\d/.test(result)) { result = "x" + result; } – abasar Sep 13 '20 at 08:20
  • 4
    @abasar what is the advatage of your slightly modified version? – run_the_race Sep 07 '22 at 07:32
4

Try this:

function toSnakeCase(inputString) {
    return inputString.split('').map((character) => {
        if (character == character.toUpperCase()) {
            return '_' + character.toLowerCase();
        } else {
            return character;
        }
    })
    .join('');
}
// x = item_name
Amats
  • 528
  • 2
  • 7
  • 1
    Thanks! This is super helpful. for me, i also added a check to ensure that the new string wont start with an underscore by replacing your `'_'` with `(index != 0 ? '_': '')` and adding index as a parameter to the map function `...map((character, index) => {...` – MoralCode Aug 02 '20 at 22:42
  • 1
    I also used the answer at https://stackoverflow.com/a/55521416/ to add an check for alphabet characters to this function so that numbers and symbols (which are the same character after making them uppercase) don't cause this function to just keep doubling the mnumber of underscores when a snake_case string is passed in. However, this also has the flaw of limiting the input to only the hardcoded character set – MoralCode Aug 02 '20 at 23:07
4

I have tested with below function and handle most of my cases

    function convertToSnakeCase(str) {
      str = str[0].toLowerCase() + str.slice(1, str.length).replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
      str  = str.replaceAll(" _","_")

      return str.replaceAll(" ","_").replace(/(^_*|_*$)/g, '');;
   }

Test cases handled

convertToSnakeCase("Payas AsdDs asD")
'payas_asd_ds_as_d'

convertToSnakeCase("Payas AsdDs")
'payas_asd_ds'

convertToSnakeCase("Pay  AsdDs")
'pay__asd_ds'

convertToSnakeCase('test_') 
'test';
Raj Saraogi
  • 1,780
  • 1
  • 13
  • 21
  • I think this solution, however, if a string ends with a space (e.g. `test `), it appends `_` (e.g. `test_`), therefore I’d suggest to remove the leading and trailing underscores as the last replacement: `const convertToSnakeCase = s => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`).replace(/ +_*/g, '_').replace(/(^_*|_*$)/g, '')`. Also the final test case result (`pay__asd_ds`) is invalid snake_case string, as it contains two consecutive `_` chars – tukusejssirs May 12 '23 at 20:41
  • 1
    My test cases: `convertToSnakeCase('Payas AsdDs asD') === 'payas_asd_ds_as_d'; convertToSnakeCase('Payas AsdDs') === 'payas_asd_ds'; convertToSnakeCase('Pay AsdDs') === 'pay_asd_ds'; convertToSnakeCase('thisIsAnExample') === 'this_is_an_example'; convertToSnakeCase('test_') === 'test';`. – tukusejssirs May 12 '23 at 20:47
  • 1
    SO formatting removed the backticks from my previous comment, therefore the following the correct code: ```const convertToSnakeCase = s => s.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`).replace(/ +_*/g, '_').replace(/(^_*|_*$)/g, '')```. – tukusejssirs May 12 '23 at 21:10
1

Accepted answer will lead with an _ if the first character is uppercase. This solves the issue.

 export function camelToSnake(string = '') {
  return (string || '')
    .replace(/([A-Z])/g, (match, group) => `_${group.toLowerCase()}`)
    .replace(/^_/, '')
}
ChatGPT
  • 5,334
  • 12
  • 50
  • 69
0

If you're willing to use external libraries, the easiest way might be to use lodash's _.snakeCase(string)

Cary Shindell
  • 1,336
  • 8
  • 25