Repository: mui/material-ui (TypeScript) — Bug Fix

Issue:
TypeError: color.charAt is not a function
<!--- Provide a general summary of the issue in the Title above -->

<!--
    Thank you very much for contributing to Material-UI by creating an issue! ❤️
    To avoid duplicate issues we ask you to check off the following list.
-->
I have some warning like this:

**TypeError: color.charAt is not a function**

decomposeColor
node_modules/@material-ui/core/esm/styles/colorManipulator.js:125

```
  122 |   return color;
  123 | }
  124 | 
> 125 | if (color.charAt(0) === '#') {
  126 |   return decomposeColor(hexToRgb(color));
  127 | }
  128 | 
```


lighten
node_modules/@material-ui/core/esm/styles/colorManipulator.js:270

Array.onUpdate
node_modules/jss-plugin-rule-value-function/dist/jss-plugin-rule-value-function.esm.js:46


Discussion:
Please provide a reproducible example. I would also check your imports and make sure they are less than 2 path levels.
I had the same error. Separate the rest of the styling from the palette. 
Something like this:
```jsx
const theme = createMuiTheme({
  palette: {
    primary: {
    },
    secondary: {    
    }
  },
  spreadIt: {
  //Do the stylings in here
  } 
})
```

When you want to spread it to different pages, do this way:
...theme.spreadIt

This worked for me. Good luck!
> I had the same error. Separate the rest of the styling from the palette.
> Something like this:
> 
> ```js-jsx
> const theme = createMuiTheme({
>   palette: {
>     primary: {
>     },
>     secondary: {    
>     }
>   },
>   spreadIt: {
>   //Do the stylings in here
>   } 
> })
> ```
> 
> When you want to spread it to different pages, do this way:
> ...theme.spreadIt
> 
> This worked for me. Good luck!

I also had the same issue, this worked for me
For anyone else with this issue, I'd just done something dumb and assigned a primary text color like this:
`text: { primary: { 500: '#467fcf' }, ... }`
rather than this:
`text: { primary: '#467fcf', ... }`
Thanks for the feedback. It sounds like we should be able to improve the error message :). The current one is cryptic. 
The comments marked off-topic are what I used to solve this same issue. 
@Mugungaman Do you have a reproduction for the error? How can we reproduce it?
**_This recreates, where 'content' is a style applied to a component..._**

_App.js:_ 

```jsx
const theme = createMuiTheme({
 ...,
  content: {
    padding: 25,
    objectFit: "cover"
  }
});
```

_Child component:_ 

```js
const styles = theme => ({
  ...theme
});
```

```jsx
<CardContent className={classes.content}>
```


**_...and this fixes it, wrapping the style name 'content' in a spreadIt object:_** 

_App.Js:_
```jsx
const theme = createMuiTheme({
...,
  spreadIt: {
    content: {
      padding: 25,
      objectFit: "cover"
    }
  }
});
```

_Child component:_ 

```jsx
const styles = theme => ({
  ...theme.spreadIt
});
```

```jsx
<CardContent className={classes.content}>
```

I have no idea how developers are creating this issue. Let's close until we have a full reproduction. 
@oliviertassinari I have reproduced this. Please check this sandbox https://codesandbox.io/s/material-uiissues16341-7mfwk
I have figured it out. The problem was due to using the colors wrongly in theme. The following code causes the error.

```
const theme = createMuiTheme({
  palette: {
    primary: {
      main: purple,
    },
    secondary: {
      main: green,
    },
  },
  status: {
    danger: "orange"
  }
});
```

The correct way to use colors in theme is as follows: (Notice that value of primary should be the color and not the main key of primary object).

```
const theme = createMuiTheme({
  palette: {
    primary: purple,
    secondary: green,
  },
  status: {
    danger: "orange"
  }
});
```

To be honest the official documentation does not consolidate all the aspects of customizing theme. It is broken down into different pages. I guess it causes some confusion.

After getting familiar with the material-ui, I was able to spot this mistake.
"@material-ui/core": "^4.9.5",

I have same issue. 

In App.js I have 

```
const theme = createMuiTheme({
  palette: {
    primary: { main: '#3f50b5' },
    secondary: { main: '#f44336' },
  },
  customError: { color: 'red' }
});
```

In child component, I have 

```
const styles = theme => ({ ...theme });
export default withStyles(styles)(Login);
```

and here is error

![1](https://user-images.githubusercontent.com/38917779/76088653-d08e1f00-5fd1-11ea-8359-ee076de49e34.PNG)
![2](https://user-images.githubusercontent.com/38917779/76088654-d126b580-5fd1-11ea-9954-6eca4d2c60b8.PNG)

> I have figured it out. The problem was due to using the colors wrongly in theme. The following code causes the error.
> 
> ```
> const theme = createMuiTheme({
>   palette: {
>     primary: {
>       main: purple,
>     },
>     secondary: {
>       main: green,
>     },
>   },
>   status: {
>     danger: "orange"
>   }
> });
> ```
> 
> The correct way to use colors in theme is as follows: (Notice that value of primary should be the color and not the main key of primary object).
> 
> ```
> const theme = createMuiTheme({
>   palette: {
>     primary: purple,
>     secondary: green,
>   },
>   status: {
>     danger: "orange"
>   }
> });
> ```
> 
> To be honest the official documentation does not consolidate all the aspects of customizing theme. It is broken down into different pages. I guess it causes some confusion.
> 
> After getting familiar with the material-ui, I was able to spot this mistake.

this doesn't fix issue for me
@gota1993 Try to reproduce it at https://codesandbox.io/ and share it so that others can debug it.
Top voted answer for this question fixed it for me.
[https://stackoverflow.com/questions/56897838/getting-a-error-typeerror-color-charat-is-not-a-function-in-c-node-modul](https://stackoverflow.com/questions/56897838/getting-a-error-typeerror-color-charat-is-not-a-function-in-c-node-modul)

Resolving patch:
diff --git a/packages/material-ui/src/styles/createPalette.js b/packages/material-ui/src/styles/createPalette.js
--- a/packages/material-ui/src/styles/createPalette.js
+++ b/packages/material-ui/src/styles/createPalette.js
@@ -132,12 +132,6 @@ export default function createPalette(palette) {
   // Bootstrap: https://github.com/twbs/bootstrap/blob/1d6e3710dd447de1a200f29e8fa521f8a0908f70/scss/_functions.scss#L59
   // and material-components-web https://github.com/material-components/material-components-web/blob/ac46b8863c4dab9fc22c4c662dc6bd1b65dd652f/packages/mdc-theme/_functions.scss#L54
   function getContrastText(background) {
-    if (!background) {
-      throw new TypeError(
-        `Material-UI: missing background argument in getContrastText(${background}).`,
-      );
-    }
-
     const contrastText =
       getContrastRatio(background, dark.text.primary) >= contrastThreshold
         ? dark.text.primary
@@ -159,21 +153,42 @@ export default function createPalette(palette) {
     return contrastText;
   }
 
-  function augmentColor(color, mainShade = 500, lightShade = 300, darkShade = 700) {
+  const augmentColor = (color, mainShade = 500, lightShade = 300, darkShade = 700) => {
     color = { ...color };
     if (!color.main && color[mainShade]) {
       color.main = color[mainShade];
     }
 
-    if (process.env.NODE_ENV !== 'production') {
-      if (!color.main) {
-        throw new Error(
-          [
-            'Material-UI: the color provided to augmentColor(color) is invalid.',
-            `The color object needs to have a \`main\` property or a \`${mainShade}\` property.`,
-          ].join('\n'),
-        );
-      }
+    if (!color.main) {
+      throw new Error(
+        [
+          'Material-UI: the color provided to augmentColor(color) is invalid.',
+          `The color object needs to have a \`main\` property or a \`${mainShade}\` property.`,
+        ].join('\n'),
+      );
+    }
+
+    if (typeof color.main !== 'string') {
+      throw new Error(
+        [
+          'Material-UI: the color provided to augmentColor(color) is invalid.',
+          `\`color.main\` should be a string, but \`${JSON.stringify(
+            color.main,
+          )}\` was provided instead.`,
+          '',
+          'Did you intend to use one of the following approaches?',
+          '',
+          'import { green } from "@material-ui/core/colors";',
+          '',
+          'const theme1 = createMuiTheme({ palette: {',
+          '  primary: green,',
+          '} });',
+          '',
+          'const theme2 = createMuiTheme({ palette: {',
+          '  primary: { main: green[500] },',
+          '} });',
+        ].join('\n'),
+      );
     }
 
     addLightOrDark(color, 'light', lightShade, tonalOffset);
@@ -183,7 +198,7 @@ export default function createPalette(palette) {
     }
 
     return color;
-  }
+  };
 
   const types = { dark, light };
 


Test patch:
diff --git a/packages/material-ui/src/styles/createPalette.test.js b/packages/material-ui/src/styles/createPalette.test.js
--- a/packages/material-ui/src/styles/createPalette.test.js
+++ b/packages/material-ui/src/styles/createPalette.test.js
@@ -5,14 +5,6 @@ import { darken, lighten } from './colorManipulator';
 import createPalette, { dark, light } from './createPalette';
 
 describe('createPalette()', () => {
-  beforeEach(() => {
-    consoleErrorMock.spy();
-  });
-
-  afterEach(() => {
-    consoleErrorMock.reset();
-  });
-
   it('should create a palette with a rich color object', () => {
     const palette = createPalette({
       primary: deepOrange,
@@ -85,26 +77,11 @@ describe('createPalette()', () => {
       pink.A400,
     );
     expect(palette.text, 'should use dark theme text').to.equal(dark.text);
-    expect(consoleErrorMock.callCount()).to.equal(0);
-  });
-
-  it('logs an error when an invalid type is specified', () => {
-    createPalette({ type: 'foo' });
-    expect(consoleErrorMock.callCount()).to.equal(1);
-    expect(consoleErrorMock.messages()[0]).to.match(
-      /Material-UI: the palette type `foo` is not supported/,
-    );
   });
 
   describe('augmentColor', () => {
     const palette = createPalette({});
 
-    it('should throw when the input is invalid', () => {
-      expect(() => {
-        palette.augmentColor({});
-      }).to.throw(/The color object needs to have a/);
-    });
-
     it('should accept a color', () => {
       const color1 = palette.augmentColor(indigo);
       expect(color1).to.deep.include({
@@ -135,20 +112,37 @@ describe('createPalette()', () => {
     });
   });
 
-  describe('getContrastText', () => {
-    it('throws an exception with a falsy argument', () => {
-      const { getContrastText } = createPalette({});
+  it('should create a palette with unique object references', () => {
+    const redPalette = createPalette({ background: { paper: 'red' } });
+    const bluePalette = createPalette({ background: { paper: 'blue' } });
+    expect(redPalette).to.not.equal(bluePalette);
+    expect(redPalette.background).to.not.equal(bluePalette.background);
+  });
+
+  describe('warnings', () => {
+    beforeEach(() => {
+      consoleErrorMock.spy();
+    });
 
-      [
-        [undefined, 'missing background argument in getContrastText(undefined)'],
-        [null, 'missing background argument in getContrastText(null)'],
-        ['', 'missing background argument in getContrastText()'],
-        [0, 'missing background argument in getContrastText(0)'],
-      ].forEach((testEntry) => {
-        const [argument, errorMessage] = testEntry;
+    afterEach(() => {
+      consoleErrorMock.reset();
+    });
 
-        expect(() => getContrastText(argument), errorMessage).to.throw();
-      });
+    it('throws an exception when an invalid type is specified', () => {
+      createPalette({ type: 'foo' });
+      expect(consoleErrorMock.callCount()).to.equal(1);
+      expect(consoleErrorMock.messages()[0]).to.include(
+        'Material-UI: the palette type `foo` is not supported',
+      );
+    });
+
+    it('throws an exception when a wrong color is provided', () => {
+      expect(() => createPalette({ primary: '#fff' })).to.throw(
+        'The color object needs to have a `main` property or a `500` property.',
+      );
+      expect(() => createPalette({ primary: { main: { foo: 'bar' } } })).to.throw(
+        '`color.main` should be a string, but `{"foo":"bar"}` was provided instead.',
+      );
     });
 
     it('logs an error when the contrast ratio does not reach AA', () => {
@@ -164,11 +158,4 @@ describe('createPalette()', () => {
       );
     });
   });
-
-  it('should create a palette with unique object references', () => {
-    const redPalette = createPalette({ background: { paper: 'red' } });
-    const bluePalette = createPalette({ background: { paper: 'blue' } });
-    expect(redPalette).to.not.equal(bluePalette);
-    expect(redPalette.background).to.not.equal(bluePalette.background);
-  });
 });