목표
SELECT col_a, col_b, ... FROM table_name ...
꼴의 쿼리 스트링에서 컬럼명들 추출하여 출력 오브젝트 형태 타입 만들기
{
colA: any;
colB: any;
...
}
AS
가 있을 경우, AS 뒤의 단어 사용
- Snake Case일 경우 Camel Case로 변환
주의사항
- 아래 타입과 같은 수준의 nesting은 옛날 타입스크립트 버전에서 호환되지 않을 수 있으므로,
반드시 타입스크립트 5.x.x 이상 버전을 사용해야 한다. (예:
"typescript": "^5.3.3”
)
→ package.json/devDependencies/typescript 확인
Type
type RemoveLineFeed<T extends string> =
T extends `\\n${infer A}` ?
A extends `${infer B}\\n` ? B
: A
: T extends `${infer A}\\n` ? A : T;
;
type Trim<T extends string, Acc extends string = '', Separator extends string = ' '>
= T extends `${infer Char}${infer Rest}`
? (Char extends Separator
? Trim<Rest, Acc>
: Trim<Rest, `${Acc}${Char}`>)
: (T extends ''
? Acc
: never);
type TrimComments<T extends string> =
T extends `${infer Head}#${any}\\n${infer Tail}`
? TrimComments<`${Head}\\n${Tail}`>
: T extends `${infer Head}--${any}\\n${infer Tail}`
? TrimComments<`${Head}\\n${Tail}`>
: T extends `${infer Head}/*${any}*/${infer Tail}`
? TrimComments<`${Head}${Tail}`>
// : T extends `${infer Head}#${any}\\r\\n${infer Tail}`
// ? TrimComments<`${Head}\\r\\n${Tail}`>
// : T extends `${infer Head}--${any}\\r\\n${infer Tail}`
// ? TrimComments<`${Head}\\r\\n${Tail}`>
: T;
type ExtractSelectBody<T extends string> =
T extends `${string}SELECT${infer Body}FROM${string}` ?
Body : never;
type SplitComma<T extends string, TUnion = never> =
T extends `${infer Head},${infer Tail}` ?
SplitComma<Tail, TUnion | Head>
: TUnion | T;
type PickAlias<T extends string> =
T extends `${any}AS ${infer Alias}` ? Alias :
T extends `${any}as ${infer Alias}` ? Alias :
T;
type SnakeToCamelCase<T extends string> =
T extends `${infer Head}_${infer Tail}` ?
`${Head}${Capitalize<SnakeToCamelCase<Tail>>}` : T;
export type ExtractOutputFromQuery<T extends string> =
T extends `${string}SELECT *${string}` ? Record<string, any> :
T extends `${string}SELECT${string}` ?
(
Record<
SnakeToCamelCase<
RemoveLineFeed<
Trim<
PickAlias<
SplitComma<
ExtractSelectBody<
TrimComments<T>
>
>
>
>
>
>
, any>
)
: any;
Examples
/*{
name: any;
pw: any;
userId: any;
yearsOld: any;
userPhoneNumber: any;
}*/
type Example_ExtractOutput = ExtractOutputFromQuery<`
SELECT user_id,
user_name AS name,
user_phone_number -- 코멘트1
,pass_word AS pw # 코멘트2
,years_old /* 코멘트3 */
FROM table
WHERE ANY_CONDITIONS
`>;