01978-medium-percentage-parser

Back

type Percentage<P, S> = S extends `${infer N}%` ? [P, N, '%'] : [P, S, ''];

type PercentageParser<A> = A extends `${infer P extends '+' | '-'}${infer S}`
  ? Percentage<P, S> : Percentage<'', A>;

Solution by alexandroppolus #36333

type before = "-"|"+"
type after = "%"

type getPre<A extends string>= A extends `${infer first}${infer R}`? first extends before ? first:"":""
type getBack<A extends string>= A extends `${getPre<A>}${infer R}` ? R extends `${infer first}${after}`? after:"":""
type getNum <A extends string>= A extends `${getPre<A>}${infer R}${getBack<A>}` ? R:""
type PercentageParser <A extends string> = [getPre<A>,getNum<A>,getBack<A>]

get every part step by step.

Solution by 985025074 #36290

// your answers
//虽然很愚蠢,但还是通过了.
type PercentageParser<A extends string> =
  A extends `${infer F}${infer R}`
  ? (F extends '+' | '-' ? [F, R] : ['', A]) extends [infer F, infer S]
  ? S extends `${infer M}%` ? [F, M, '%'] : [F, S, '']
  : never
  : ['', '', '']

Solution by goddnsgit #36197

type S4<Str, Result extends unknown[]> = Str extends '' ? Result : never

type S3<
  Str,
  Result extends unknown[],
> = Str extends `${infer First extends '%'}${infer Rest}`
  ? S4<Rest, [...Result, First]>
  : S4<Str, [...Result, '']>

type S2<
  Str,
  Result extends unknown[],
  N extends string = '',
> = Str extends `${infer First extends number}${infer Rest}`
  ? S2<Rest, Result, `${N}${First}`>
  : S3<Str, [...Result, N]>

type S1<Str, Result extends unknown[]> = Str extends `${infer First extends
  | '+'
  | '-'}${infer Rest}`
  ? S2<Rest, [...Result, First]>
  : S2<Str, [...Result, '']>

type PercentageParser<A extends string> = S1<A, []>

Image

wiki: Nondeterministic_finite_automaton

Solution by Autumnal-Joy #36196

More verbose approach.

type NeverDefault<T, TDefault> = 
  [T] extends [never]
    ? TDefault
    : T;

type GetSign<T extends string> =
  T extends `${infer Sign extends '-' | '+'}${infer _}`
    ? Sign
    : never;

type GetPercentageSign<T extends string> = 
  T extends `${infer Rest}%`
    ? '%'
    : never;

type RemoveSign<T extends string> =
  T extends `${ '-' |'+' }${infer Rest}`
    ? Rest
    : T;

type RemovePercentageSign<T extends string> =
  T extends `${infer Rest}%`
    ? Rest
    : T;

type GetValue<T extends string> = RemovePercentageSign<RemoveSign<T>>; 

type PercentageParser<T extends string> = 
  [
    NeverDefault<GetSign<T>, ''>,
    NeverDefault<GetValue<T>, ''>,
    NeverDefault<GetPercentageSign<T>, ''>,
  ];

Solution by Rikkun-1 #36174

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

Solution by vaclock #35930

type PercentageParser<A extends string> = A extends `${infer F}${infer L}`
  ? F extends '-' | '+'
    ? L extends `${infer L1}%`
      ? [F, L1, '%']
      : [F, L, '']
    : A extends `${infer L2}%`
    ? ['', L2, '%']
    : ['', A, '']
  : ['', '', ''];

Solution by RanungPark #35577

// your answers
type PercentageParser<A extends string, S extends string = '', N extends string = '', P extends string = ''> = A extends `${infer First}${infer Rest}`
  ? First extends '+' | '-'
    ? PercentageParser<Rest, First, N, P>
    : First extends '%'
      ? [S, N, '%']
      : PercentageParser<Rest, S, `${N}${First}`, P>
  : [S, N, P];

Solution by AndreGeng #34754

type PercentageParser<T extends string> = 
  T extends `${infer Start}${infer Middle}%` ? 
    Start extends '-' | '+' ? 
      [Start, Middle, '%'] :  ["", `${Start}${Middle}`, '%'] : 
  T extends `${number}` ? ['', T, ''] : ['', '', ''];

Solution by semet #34677

// 你的答案
type CheckNumber<T extends string> = T extends `${infer Num}%`?[Num,"%"]:[T,""]

type PercentageParser<A extends string> = 
A extends `${infer Sign extends '-'|'+'}${infer R}` ? [Sign,...CheckNumber<R>]:['',...CheckNumber<A>]

Solution by Jayce-liang #34634

type CheckSuffix<T> =  T extends `${infer P}%` ? [P, '%'] : [T, ''];
type CheckPrefix<T> = T extends "+" | "-" ? T : never

type PercentageParser<A extends string> = A extends `${CheckPrefix<infer First>}${infer Rest}` ?  [First, ...CheckSuffix<Rest> ] : ['', ...CheckSuffix<A>]

Solution by devshinthant #34628

type PercentageParser<A extends string> = A extends `${Perfix<infer P>}${infer V}` ? [P, ...Suffix<V>] : ['', ...Suffix<A>]

Solution by ouzexi #34043

// 你的答案
type DealRestLetters<T extends string> = T extends `${infer A}%` ? [A, '%'] : [T, '']
type PercentageParser<A extends string> = A extends `${infer T extends '+' | '-'}${infer F}` ? [T, ...DealRestLetters<F>] : ['', ...DealRestLetters<A>]

Solution by heyuelan #33695

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 sdrjs #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