Skip to content

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

Description

@rrabmig

Current behaviour:
The cn() helper can create a formatter in two different ways:

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.

/* 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
/* 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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions