bem / bem/bem-react

@bem-react/classname: Unclear typing for element-bound class name formatters

Open
#636 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.