跳到主要内容

BEM Style String

介绍

BEM是CSS中类的流行的命名规范.

例如, 用btn表示块元素, 依赖于块元素的将用btn__price表示, 改变块样式的修饰符适用btn--bigbtn__price--warning来修饰. 执行BEM<B,E,M>,从3个参数中生成联合字符串. B是字符字面量, E和M是字符数组(也可能是空的).

ts
ts
View on GitHub

起点

ts
/* _____________ Your Code Here _____________ */
 
type BEM<B extends string, E extends string[],M extends string[]> = any
 
/* _____________ Test Cases _____________ */
 
type cases = [
Expect<Equal<BEM<'btn', ['price'], []>, 'btn__price'>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<BEM<'btn', ['price'], ['warning', 'success']>, 'btn__price--warning' | 'btn__price--success' >>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<BEM<'btn', [], ['small', 'medium', 'large']>, 'btn--small' | 'btn--medium' | 'btn--large' >>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
ts
/* _____________ Your Code Here _____________ */
 
type BEM<B extends string, E extends string[],M extends string[]> = any
 
/* _____________ Test Cases _____________ */
 
type cases = [
Expect<Equal<BEM<'btn', ['price'], []>, 'btn__price'>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<BEM<'btn', ['price'], ['warning', 'success']>, 'btn__price--warning' | 'btn__price--success' >>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Equal<BEM<'btn', [], ['small', 'medium', 'large']>, 'btn--small' | 'btn--medium' | 'btn--large' >>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
take the challenge

解决方案

Spoiler warning // Click to reveal answer
ts
// most popular
type BEM<B extends string, E extends string[], M extends string[]> = `${B}${E extends [] ? '' : `__${E[number]}`}${M extends [] ? '' : `--${M[number]}`}`
 
ts
// most popular
type BEM<B extends string, E extends string[], M extends string[]> = `${B}${E extends [] ? '' : `__${E[number]}`}${M extends [] ? '' : `--${M[number]}`}`
 
ts
// my solution
/**
* 如果E类型数组中有多个元素,就不能处理.
*/
type addModifierLine<Pre extends string, A extends any[]> = A['length'] extends 0
? A
: A extends [infer F extends string, ...infer R]
? `${Pre}${F}` | (R['length'] extends 0 ? never : addModifierLine<Pre, R>)
: A;
 
 
type addModifierLineToArrEle<Pre extends string, A extends any[]> = A extends [infer F extends string, ...infer R]
? [`${Pre}${F}`, ...addModifierLineToArrEle<Pre, R>]
: [];
 
type mergeEAndM2<E extends string[], M extends string[]> =
M['length'] extends 0
? E
: E extends [infer F extends string]
? addModifierLineToArrEle<F, M>
: M;
 
 
 
type BEM<B extends string, E extends string[], M extends string[]> =
addModifierLine<B, mergeEAndM2<addModifierLineToArrEle<'__', E>, addModifierLineToArrEle<'--', M>>>
 
ts
// my solution
/**
* 如果E类型数组中有多个元素,就不能处理.
*/
type addModifierLine<Pre extends string, A extends any[]> = A['length'] extends 0
? A
: A extends [infer F extends string, ...infer R]
? `${Pre}${F}` | (R['length'] extends 0 ? never : addModifierLine<Pre, R>)
: A;
 
 
type addModifierLineToArrEle<Pre extends string, A extends any[]> = A extends [infer F extends string, ...infer R]
? [`${Pre}${F}`, ...addModifierLineToArrEle<Pre, R>]
: [];
 
type mergeEAndM2<E extends string[], M extends string[]> =
M['length'] extends 0
? E
: E extends [infer F extends string]
? addModifierLineToArrEle<F, M>
: M;
 
 
 
type BEM<B extends string, E extends string[], M extends string[]> =
addModifierLine<B, mergeEAndM2<addModifierLineToArrEle<'__', E>, addModifierLineToArrEle<'--', M>>>
 
view more solutions