01978-medium-percentage-parser

Back

type Num = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type PercentageParser<A extends string, C extends string[] = []> =
  C['length'] extends 0
    ? A extends `${infer H}${infer R}`
      ? H extends '+' | '-'
        ? PercentageParser<R, [H]>
        : PercentageParser<A, ['']>
      : ['', '', '']
    : C['length'] extends 1
        ? A extends `${infer H}${infer R}`
          ? H extends Num
            ? PercentageParser<R, [...C, H]> 
            : PercentageParser<A, [...C, '']>
          : [...C, '', '']
        : C['length'] extends 2
          ? A extends `${infer H}${infer R}`
            ? H extends Num
              ? PercentageParser<R, [C[0], `${C[1]}${H}`]>
              : [...C, H]
            : [...C, '']
          : never

Solution by all-user #33120

type GetNumbersFromString<T extends string, Acc extends string = ""> = T extends `${infer F}${infer Rest}`
  ? F extends `${infer N extends number}` ? GetNumbersFromString<Rest, `${Acc}${N}`> : GetNumbersFromString<Rest, Acc>
  : Acc
  
type GetOperatorFromPercentage<T extends string> = T extends `${infer O extends '+' | '-'}${string}` ? O : ''

type GetPercentageSymbolFromString<T extends string> = T extends `${string}${infer S extends '%'}` ? S : ''

type PercentageParser<T extends string> = [
  GetOperatorFromPercentage<T>,
  GetNumbersFromString<T>,
  GetPercentageSymbolFromString<T>
]

Solution by ZhulinskiiDanil #32723

type CheckPrefix<T> = T extends '+' | '-' ? T : never;
type CheckSuffix<T> =  T extends `${infer P}%` ? [P, '%'] : [T, ''];
type PercentageParser<A extends string> = A extends `${CheckPrefix<infer L>}${infer R}` ? [L, ...CheckSuffix<R>] : ['', ...CheckSuffix<A>];

처음에 Prefix, Value, Suffix의 개념으로 접근하여 풀지 못하였는데 위의 CheckSuffix 타입으로 한번에 원하는 타입을 만들 수 있는 방법을 새로 배웠다.

Solution by dev-hobin #32485

type NumberUnion = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";

type AppendBlankString<T extends string[]> = T['length'] extends 2 
  ?
    [...T, '']
  :
    [...T, '', '']
    

type PercentageParser<A extends string, Acc extends string[] = [], NumAcc extends string = ''> = A extends `${infer H}${infer T}` 
  ?
     H extends NumberUnion 
      ? 
        PercentageParser<T, Acc,`${NumAcc}${H}`>    
      : 
        H extends "%"
          ?
            Acc extends [] 
              ? 
                PercentageParser<T, ["", NumAcc, H],`${NumAcc}`> 
              : 
                PercentageParser<T, [...Acc, NumAcc, H],`${NumAcc}`> 
          : 
            PercentageParser<T, [...Acc, `${H}`],`${NumAcc}`>
  : 
    Acc['length'] extends 3 
      ?
        Acc
      : 
        Acc extends [] 
          ?
            ["", NumAcc, ""]
          :
            AppendBlankString<[...Acc, NumAcc]>```

Solution by keyurparalkar #32330

type PercentageInternal<T> = 
  T extends `${infer A}%`
    ? [A, '%'] 
    : [T, '']
;

type PercentageParser<T extends string> = 
  T extends `${infer Head}${infer Tail}` 
    ? Head extends '+' | '-' 
      ? [Head, ...PercentageInternal<Tail>] 
      : ['', ...PercentageInternal<T>]
    : ['', '', '']
;

Solution by RusJstudent #31486

// your answers
type PercentageParser<A extends string,
  First extends string = A extends `${infer F extends '+' | '-'}${infer _}` ? F : '',
  Last extends string = A extends `${infer _}%` ? '%' : ''
> = [
    First,
    A extends `${First}${infer _}${Last}` ? _ : never,
    Last
  ]

Solution by yangdonglai #30733

type CheckL<T extends string> = T extends `${ infer U }%` ? [U, '%'] : [T, '']

type PercentageParser<A extends string> = A extends `${ infer B extends '+' | '-' }${ infer C }` ? [B, ...CheckL<C>] : ['', ...CheckL<A>]

Solution by Yirujet #30466

This approach is to iterate the input string letter by letter and check the first letter in each iteration and save each symbol to return in placeholders defined in the genric types until the iteration process has reached the end when A becomes an empty string, then we return the collected results in an array.

type PercentageParser<A extends string, Operator = '', Number = '', Percentage = ''> = 
A extends `${infer Head}${infer Rest}` 
  ? Head extends '+' | '-' ? PercentageParser<Rest, Head> 
  : Head extends '%' ? PercentageParser<Rest, Operator, Number, Head> 
  : PercentageParser<Rest, Operator, `${Number & string}${Head}`> 
: [Operator, Number, Percentage]

Solution by qianzhong516 #30029

type PercentageParser<A extends string, S = '', U = ''> =
  A extends `${infer S extends '+' | '-'}${infer R}` ? PercentageParser<R, S, U> :
  A extends `${infer R}%` ? PercentageParser<R, S, '%'> :
  [S, A, U]

Solution by sbr61 #29984

type GetPercent<A extends string> = A extends `${infer Rest}%` ? [Rest, "%"] : [A, ""]
type GetSign<A extends [string, "" | "%"]> = 
  A[0] extends `+${infer Rest}` ?
    ["+", Rest, A[1]] :
    A[0] extends `-${infer Rest}` ?
      ["-", Rest, A[1]] :
      ["", A[0], A[1]]

type PercentageParser<A extends string> = GetSign<GetPercent<A>>

Better one*

type ExtractSign<A extends string> =
  A extends `+${infer Rest}` ?
    ['+', Rest] :
    A extends `-${infer Rest}` ?
      ['-', Rest] :
      ['', A]
  
type PercentageParser<A extends string> =
  A extends `${infer Begining}%` ?
    [...ExtractSign<Begining>, '%'] :
    [...ExtractSign<A>, '']

Solution by maximallain #29923

type PrefixParser<A extends string> = A extends `${infer Prefix extends '+' | '-'}${infer Rest extends string}` ? [Prefix, Rest] : ['', A]
type SuffixParser<A extends string> = A extends `${infer Rest extends string}%` ? [Rest, '%'] : [A, '']
type PercentageParser<A extends string> = [PrefixParser<A>[0], ...SuffixParser<PrefixParser<A>[1]>]

Solution by normacdylan #29630

全是if/else

type PString1 = '+85%';
type PString2 = '85%';
type PString3 = '85';

type PercentageParser<T extends string> = T extends `${infer A}${infer B}` ?
    A extends '-' | '+' ?
        B extends `${infer E}%`?
                [A, E, '%']: 
            [A, B, '']: 
        `${A}${B}` extends `${infer R}%`?
            ['', R, '%']: 
            ['', `${A}${B}`, '']: 
    ['', '', ''];

type RR1 = PercentageParser<PString3>;

Solution by sundial-dreams #29477

// your answers
type ParseSign<T extends string> = 
  T extends `${infer Sign extends '+' | '-'}${string}`
    ? Sign
    : ''


type ParsePercent<T extends string> = 
  T extends `${string}${infer Percent extends '%'}`
    ? Percent
    : ''

type ParseNum<T extends string> =
  T extends `${ParseSign<T>}${infer Num}${ParsePercent<T>}`
    ? Num
    : ''

type PercentageParser<A extends string> = [
  ParseSign<A>,
  ParseNum<A>,
  ParsePercent<A>
]

Solution by ChengYaoYan #29432

type FindPlusOrMinus<S> = S extends `${infer P}${string}` ? (P extends "+" | "-" ? P : "") : ""
type FindNumber<S> = S extends `${"+" | "-"}${infer Number}${"%"}` 
  ? Number 
  : S extends `${""}${infer Number}${"%"}` 
      ? Number 
      : S extends `${"+" | "-"}${infer Number}${""}` 
          ? Number 
          : S extends `${""}${infer Number}${""}` 
              ? Number 
              : "";
type FindPercent<S> = S extends "%" ? S : S extends `${string}${infer P}` ? (P extends "%" ? P : FindPercent<P>) : ""

type PercentageParser<A extends string> = [FindPlusOrMinus<A>, FindNumber<A>, FindPercent<A>]

Solution by hajeonghun #28824

type CheckPrefix = T extends "+" | "-" ? T : never; type CheckSuffix = T extends ${infer Num}% ? [Num, "%"] : [T, ""]; type PercentageParser = A extends `${CheckPrefix< infer Prefix

}${infer R}` ? [Prefix, ...CheckSuffix] : ["", ...CheckSuffix];

Solution by DoubleWoodLin #28659

type Operator = "+" | "-";
type Percent = "%";

type DropPercent<S extends string> = S extends `${infer N}${Percent}` ? N : S;
type DropOperator<S extends string> = S extends `${Operator}${infer N}` ? N : S;

type OperateParser<S extends string> = S extends `${infer O}${string}`
  ? O extends Operator
    ? O
    : ""
  : "";
type PercentParser<S extends string> = S extends `${string}${Percent}`
  ? Percent
  : "";

type PercentageParser<S extends string> = [
  OperateParser<S>,
  DropPercent<DropOperator<S>>,
  PercentParser<S>
];

Solution by DoGukKim #28337

// your answers
type PercentageParser<A extends string, T extends string [] = ['', '', '']> = A extends '' 
? T
: A extends `${infer F}${infer R}`
  ?  F extends '%'
     ? PercentageParser<R, [`${T[0]}`, `${T[1]}`, `${T[2]}${F}`]>
     : F extends '+' | '-'
       ? PercentageParser<R, [`${T[0]}${F}`, `${T[1]}`, `${T[2]}`]>
       : PercentageParser<R, [`${T[0]}`, `${T[1]}${F}`, `${T[2]}`]>
  // 一个 % + -
  : A extends '%'
    ? PercentageParser<'', [`${T[0]}`, `${T[1]}`, `${T[2]}${A}`]>
    : A extends '+' | '-'
      ? PercentageParser<'', [`${T[0]}${A}`, `${T[1]}`, ``]>
      : PercentageParser<'', T>

Solution by ixiaolong2023 #27787

type NBR = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";

type PercentageParser<
  A extends string,
  O extends string = "",
  N extends string = "",
  P extends string = ""
> = A extends `${infer H}${infer T}`
  ? PercentageParser<
      T,
      H extends "+" | "-" ? H : O,
      H extends NBR ? `${N}${H}` : N,
      H extends "%" ? H : P
    >
  : [O, N, P];

Solution by idebbarh #27651

type IsSigns<T> = T extends '+' | '-' ? T : never;

type GetNumber<T> = 
  T extends `${IsSigns<infer R>}${infer L}` 
  ? [R, L] 
  : ['', T]

type PercentageParser<A extends string> = A extends `${infer R}%`
  ? [...GetNumber<R>, '%']
  : [...GetNumber<A>, '']

Solution by AwesomeYelim #27458

// your answers

type checkPrefix<T> = T extends '+' | '-' ? T : never;
type checkSuffix<T> = T extends `${infer P}%` ? [P, '%'] : [T, ''];
type PercentageParser<A extends string> = A extends `${checkPrefix <infer L>}${infer R}` ? [L, ...checkSuffix<R>] : ['', ...checkSuffix<A>]

Solution by GreattitJY #27287

// 你的答案

type ParserX<A extends string> = A extends `+${infer X}` ? '+' : A extends `-${infer X}` ? '-' : '';

type ParserZ<A extends string> = A extends `${infer Z}%` ? '%' : '';

type ParserY<A extends string> = A extends `${ParserX<A>}${infer Y}${ParserZ<A>}` ? Y : '';

type PercentageParser<A extends string> = [ParserX<A>, ParserY<A>, ParserZ<A>]

Solution by 774653363 #27157


type PercentageParser<A extends string, X extends string='', Y extends string=''> = A extends `${infer F}${infer O}` ?
  F extends '+' | '-' ? PercentageParser<O, F> : 
  F extends '%' ? [X, Y, '%'] : PercentageParser<O, X, `${Y}${F}`> :
  [X, Y, '']

Solution by 8471919 #26899

type GetPrefix<S> = S extends `${infer F}${string}` ? F extends '+' | '-' ? F : '' : '';
type GetSuffix<S> = S extends `${number | ''}%` ? '%' : '';
type GetNumber<S> = S extends `${'+' | '-'}${infer N}` ? N extends `${infer N1}${'%'}` ? N1 : N : S extends `${infer N2}${'%'}` ? N2 : S;
type PercentageParser<A extends string> = [GetPrefix<A>, GetNumber<A>, GetSuffix<A>]

Solution by smileboyi #26876

// 你的答案
type PercentageParser<T extends string, Arr extends [string, string, string] = ['', '', '']> = T extends `${infer S extends '+' | '-'}${infer L}` ?
    PercentageParser<L, [S, Arr[1], Arr[2]]> :
    T extends `${infer S extends number}${infer R}` ? PercentageParser<R, [Arr[0], `${Arr[1]}${S}`, Arr[2]]> :
    T extends `%` ? PercentageParser<'', [Arr[0], Arr[1], '%']> : Arr;

Solution by Hencky #26486

type PercentageParser<A extends string> = 
A extends `${infer SIGN extends '+' | '-'}${infer NUM}%` ? [SIGN, NUM, '%'] :
A extends `${infer SIGN extends '+' | '-'}${infer NUM}` ? [SIGN, NUM, ''] :
A extends `${infer NUM}%` ? ['', NUM, '%'] :
A extends `${infer NUM}` ? ['', NUM, ''] 
: ['','','']

Solution by kkirico #26317

// 你的答案
type Sign="+" | "-" 
type Unit="%" 
type ParseUnit<A extends string>= A extends `${infer Content}${Unit}`? [Content,Unit]:[A,'']

type PercentageParser<A extends string> =  A extends `${Sign}${infer Content}`
                                              ? [A extends `${infer X}${Content}`?X:'',...ParseUnit<Content>]
                                           : ['',...ParseUnit<A>]

Solution by guilipan #26277

// your answers
type CheckPrefix<T> = T extends '+' | '-' ? T : never;
type CheckSuffix<T> =  T extends `${infer P}%` ? [P, '%'] : [T, ''];
type PercentageParser<A extends string> = A extends `${CheckPrefix<infer L>}${infer R}` ? [L, ...CheckSuffix<R>] : ['', ...CheckSuffix<A>];

Solution by daiki-skm #26228

type PlusMinusParser<T extends string> = T extends `${infer F}${infer R}` ? F extends '+' | '-' ? [F, R] : ['', T] : ['', ''];
type PercentageParser <A extends string> = PlusMinusParser<A> extends [infer F, infer S] ? S extends `${infer N}%` ? [F, N, '%'] : [F, S, ''] : PlusMinusParser<A>;

Solution by kakasoo #25978

type Empty = "";
type Prefix = "-" | "+" | "##";
type Suffix = "%" | "@@";

type cases = [
  Expect<Equal<PercentageParser<''>, ['', '', '']>>,
  Expect<Equal<PercentageParser<'123'>, ['', '123', '']>>,
  Expect<Equal<PercentageParser<'+'>, ['+', '', '']>>,
  Expect<Equal<PercentageParser<'%'>, ['', '', '%']>>,
  Expect<Equal<PercentageParser<'+123'>, ['+', '123', '']>>,
  Expect<Equal<PercentageParser<'123%'>, ['', '123', '%']>>,
  Expect<Equal<PercentageParser<'+123%'>, ['+', '123', '%']>>,
  // support more prefix and suffix
  Expect<Equal<PercentageParser<'123@@'>, ['', '123', '@@']>>,
  Expect<Equal<PercentageParser<'##123'>, ['##', '123', '']>>,
  Expect<Equal<PercentageParser<'##123@@'>, ['##', '123', '@@']>>,
];

type HandleSuffix<A extends string, P extends string> = A extends P
  ? [Empty, A]
  : A extends `${infer Head}${P}`
  ? A extends `${Head}${infer Tail}`
    ? [Head, Tail]
    : never
  : [A, Empty];

type HandlePrefix<A extends string, P extends string> = A extends P
  ? [A, Empty]
  : A extends `${P}${infer Tail}`
  ? A extends `${infer Head}${Tail}`
    ? [Head, Tail]
    : never
  : [Empty, A];

type PercentageParser<A extends string> = HandlePrefix<A, Prefix> extends [
  infer P,
  infer V
]
  ? V extends string
    ? [P, ...HandleSuffix<V, Suffix>]
    : never
  : never;

Solution by EuphoriaCHN #25782

// your answers
type PercentageParser<T extends string, S = ''> = T extends `${infer H extends '+' | '-'}${infer R}`
  ? PercentageParser<R, H>
  : T extends `${infer N}%`
    ? [S, N, '%']
    : [S, T, '']

Solution by CheolMinBae #25571