@bem-react/classname: Unclear typing for element-bound class name formatters
- Dominant language
- TypeScript
- Stars
- 450
- Forks
- 69
- PR merge metrics
- No merged PRs in 30d
Description
**Current behaviour:**
The `cn()` helper can create a formatter in two different ways:
```ts
const cnBlock = cn('Block');
const cnBlockElement = cn('Block', 'Element');
```
Both values are currently typed as `ClassNameFormatter`, but the second form behaves differently and makes part of the callable API misleading.
```ts
/* block formatter*/
const cnBlock = cn('Block');
cnBlock('Element'); // => Block-Element
cnBlock('Element', { mod: true }); // => Block-Element Block-Element_mod
cnBlock({ mod: true }); // => Block Block_mod
```
```ts
/* element formatter*/
const cnBlockElement = cn('Block', 'Element');
cnBlockElement('Element2', { mod: true }); // => Block-Element Block-Element_mod
cnBlockElement({ mod: true }); // => Block-Element Block-Element_mod
```
**Problem:** the first argument `'Element2'` in this call is accepted by types, but has no effect. This makes the type contract unclear. For an element-bound formatter, passing another element name is meaningless: the element is already fixed when the formatter is created and Block-Element-Element can't exist as well.
**Suggestion:** the two formatter creation patterns should have different return types:
`ClassNameFormatter]`= for block formatters created by the one-argument form
`ClassNameElementFormatter`- for element-bound formatters created by the two strings
```ts
cnBlockElement('Element2', { mod: true });
// should be a TypeScript error
```
**Notes:**
- Not a runtime bug
- Bump will be safe since first argument was doing nothing
- I am ready to fix that
Contributor guide
Research direction
Start by locating the cn() helper and the ClassNameFormatter type declarations in @bem-react/classname. Compare the one-argument and two-string creation forms, introduce the distinct element-bound typing described in the issue, and add or update TypeScript checks so passing a second element name is rejected while modifier calls remain valid.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100