Logo
Hyunsu Blog
typescript-generic-mappedType

๐Ÿ“†Published :Aug 3, 2023 โ€ข

๐Ÿ“†Updated :Aug 3, 2023 โ€ข

โ˜•๏ธ3min

<ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™œ์šฉํ•˜์—ฌ ์ข€ ๋” ๋‚˜์€ ์ƒ์‚ฐ์„ฑ ์–ป๊ธฐ>์‚ฌ์šฉ์ž ํ–‰๋™ ๋ถ„์„ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ํƒ€์ž… ๊ฐœ์„ ๊ธฐ

์•ˆ๋…•ํ•˜์„ธ์š”,

์˜ค๋Š˜์€ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์™€ ๊ทธ ํ•ด๊ฒฐ์ฑ…, ๊ทธ๋ฆฌ๊ณ  ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋„์ž…ํ•˜์—ฌ ์–ป์€ ๊ฐœ์„  ๊ธฐํšŒ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ์  ํŒŒ์•…

๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ์™€ ์ด๋ฒคํŠธ ๋ช…์„ธ์„œ๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ, ๋ฌด๋ ค 100๊ฐœ๊ฐ€ ๋„˜๋Š” ์ด๋ฒคํŠธ์™€ ๊ทธ์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ๋“ค์ด ์žˆ์—ˆ๋Š”๋ฐ์š”. ์ด ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์—์„œ๋Š” ํœด๋จผ ์—๋Ÿฌ๊ฐ€ ์—†์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์ง€๋งŒ, ๊ทธ๋Ÿฐ ๋ณด์žฅ์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

typescript generic4

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด์ง„ clickPayNow ์ด๋ฒคํŠธ ๋‚ด์˜ ๋‹ค๋ฅธ ์†์„ฑ์„ ์ ‘๊ทผํ•  ๋•Œ ์˜คํƒ€๊ฐ€ ์žˆ๋Š” ์†์„ฑ์— ์ ‘๊ทผํ•˜๋ฉด undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์ƒํƒœ์—์„œ ์ด undefined ๊ฐ’์— ์ ‘๊ทผํ•˜๋ ค ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด JavaScript์—์„œ๋Š” ์—ด์‹ฌํžˆ ๋ฐฉ์–ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” null ๋˜๋Š” undefined๋ฅผ ์ฒดํฌํ•˜๊ฑฐ๋‚˜ optional chaining์œผ๋กœ ์ฒดํฌํ•˜๋Š” ๋ฐฉ๋ฒ• ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” ์ฝ”๋“œ ํ’ˆ์งˆ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ  ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ง„์˜์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์ž‘์—…์ด ๋ฒˆ๊ฑฐ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ ๊ทน์ ์œผ๋กœ ๋„์ž…ํ•˜์—ฌ ์ƒ์‚ฐ์„ฑ๊ณผ ์ •ํ™•๋„๋ฅผ ๋†’์ด๋Š” ๋ฐฉ์•ˆ์„ ๋ชจ์ƒ‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํƒ€์ž… ์ ์šฉํ•˜๊ธฐ

๋จผ์ € ssomeeMixpanel.track()์ด๋ž€ ํ•จ์ˆ˜๋Š” ์ด๋ฒคํŠธ ๋ช…์„ธ์„œ์— ์ •์˜๋œ ์ด๋ฒคํŠธ ์ด๋ฆ„๊ณผ ์ด๋ฒคํŠธ ์ด๋ฆ„์— ํ•ด๋‹น๋˜๋Š” ์†์„ฑ๋“ค์„ ์ธ์ž๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ mixpanel API๋กœ ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export const ssomeeMixpanel = () => { return { track(eventType, properties) { // ํ•จ์ˆ˜ ๊ตฌํ˜„... try { mixpanel.track(eventType, properties); return; } catch (error) { console.warn(`fail to send to mixpanel eventName: ${eventType}`); } }, } } ssomeeMixpanel.track("page_viewed", "" )

track() ํ•จ์ˆ˜์— ํƒ€์ž…์„ ์ ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ €์˜ ์ฒซ ์‹œ๋„๋Š” ์ด๋ฒคํŠธ์ด๋ฆ„์— ์œ ๋‹ˆ์˜จ์„ ์ด์šฉํ•˜์ž๋Š” ๊ฑฐ์˜€์Šต๋‹ˆ๋‹ค. ์œ ๋‹ˆ์˜จ ํƒ€์ž…์€ ํ•ฉ์ง‘ํ•ฉ์˜ ๊ฐœ๋…์œผ๋กœ ์ด ํƒ€์ž… ๋˜๋Š” ์ € ํƒ€์ž…์„ ํ—ˆ์šฉํ•˜๊ฒŒ ํ•˜๋Š” ํƒ€์ž…์ž…๋‹ˆ๋‹ค. eventType์˜ ์ธ์žํƒ€์ž…์œผ๋กœ page_viewed ๋˜๋Š” "sign_up" ๋˜๋Š” "login" ์ด ๋ฉ๋‹ˆ๋‹ค.

type MixpanelEventName= "page_viewed"| "sign_up"| "login" interface MixpanelProperties { page_path?: string; tab_viewed?: string; scroll?: number; } export const ssomeeMixpanel = () => { return { track(eventType:MixpanelEventName , properties: MixpanelProperties) { // ํ•จ์ˆ˜ ๊ตฌํ˜„... try { mixpanel.track(eventType, properties); return; } catch (error) { console.warn(`fail to send to mixpanel eventName: ${eventType}`); } }, } }

์œ ๋‹ˆ์˜จ ํƒ€์ž… ์„ค์ • ๋งŒ์œผ๋กœ๋„ ์•„๋ž˜์˜ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด ์ด๋ฒคํŠธ ์ด๋ฆ„๊ณผ ์†์„ฑ์—์„œ ์ž๋™ ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , Excel ํŒŒ์ผ๋กœ ์ด๋ฒคํŠธ ์ด๋ฆ„์„ ํ™•์ธํ•˜๋Š” ์ˆ˜๊ณ ๋ฅผ ๋œ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

typescript generic typescript generic 2

ํ•˜์ง€๋งŒ ์—‘์…€ํŒŒ์ผ์„ ์™”๋‹ค๊ฐ”๋‹ค ํ•˜๋ฉด์„œ ์ด๋ฒคํŠธ์— 30๊ฐœ๊ฐ€ ๋„˜๋Š” ์†์„ฑ์— ์–ด๋–ค๊ฑธ ๊ณจ๋ผ์•ผ ํ• ์ง€ ๋งค๋ฒˆ ํ™•์ธํ•ด์•ผ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์œ ๋‹ˆ์˜จ ํƒ€์ž…์€ ํ•ฉ์ง‘ํ•ฉ๊ณผ ๊ฐ™์€ ๊ฐœ๋…์œผ๋กœ, ์—ฌ๋Ÿฌ ํƒ€์ž… ์ค‘ ํ•˜๋‚˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์ •์˜๋œ ๋ชจ๋“  ํƒ€์ž…์„ ํฌ๊ด„ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ ์งธ ์ธ์ž์— ๋”ฐ๋ผ ๋‘๋ฒˆ์งธ ์ธ์ž์—์„œ ์ž๋™ ์ถ”๋ก  ๋˜๋Š” ํƒ€์ž…์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ํƒ€์ž…์„ ๋Š์Šจํ•˜๊ฒŒ ์ •์˜ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ด๋ฒคํŠธ ์†์„ฑ์„ ์ •ํ™•ํ•˜๊ณ  ์‹ ์†ํ•˜๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ๋” ์œ ๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋น„๋ก ๋‚˜์ค‘์— ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ํ˜„์žฌ ์ €ํฌ๊ฐ€ ์ง๋ฉดํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ๋Š” ์ด ๋ฐฉ๋ฒ•์ด ๋” ์ ํ•ฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”. ๊ทธ๋ž˜์„œ ์ฒซ๋ฒˆ ์งธ ์ธ์ž์˜ ํƒ€์ž…์— ๋”ฐ๋ผ, ๋‘๋ฒˆ ์งธ ์ธ์ž์˜ ํƒ€์ž…์„ ์—„๊ฒฉํ•˜๊ฒŒ ์ ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ œ๊ฐ€ ์›ํ•˜๋Š”๊ฑด ํŠน์ • eventType์„ ์„ ํƒํ•˜๋ฉด, event์— ํ•ด๋‹นํ•˜๋Š” properties๋“ค์ด ์ž๋™์œผ๋กœ ์ถ”๋ก ๋˜๊ธฐ๋ฅผ ๋ฐ”๋žฌ์–ด์š”.

properties ์ธ์ž ์ž๋ฆฌ์—์„œ๋Š” ์–ด๋–ค eventType์„ ์„ ํƒํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋ฐ”๋กœ ์ œ๋„ค๋ฆญ์„ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด, ํŠน์ • ํƒ€์ž…์„ ์ž…๋ ฅ๋ฐ›์•„ ๊ทธ์— ๋”ฐ๋ผ ๋ฐ˜ํ™˜๋˜๋Š” ํƒ€์ž…์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ์ œ๋„ค๋ฆญ T๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ track() ์˜ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ด๋ฒคํŠธ ๋„ค์ž„๋“ค ์ค‘ ํ•˜๋‚˜๋งŒ ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํƒ€์ž… ์ œ์•ฝ์„ ๋‘ก๋‹ˆ๋‹ค.

track<T extends MixpanelEventName>(eventType:T, properties: ){ },

๊ทธ๋ฆฌ๊ณ  ์ฒซ๋ฒˆ ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์‚ฌ์šฉํ•˜๋˜ T๊ฐ€ , ๋‘๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ properties๋ฅผ ๊ฒฐ์ •ํ•  ๋•Œ ์–ด๋–ค ์ด๋ฒคํŠธ ๋„ค์ž„์„ ์‚ฌ์šฉํ–ˆ๋Š”์ง€ ์•Œ๊ธฐ ์œ„ํ•ด T๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„  ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์€ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ํƒ€์ž…์„ ๋‹ค๋ฅด๊ฒŒ ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์กฐ๊ฑด๋ถ€ ํƒ€์ž…์„ ํ™œ์šฉํ•˜์—ฌ ๊ฐœ์„ ์„ ํ•ด๋ณด์ฃ !

์ผ๋‹จ ๋จผ์ € ์ด๋ฒคํŠธ ์ •์˜์„œ์— ๋”ฐ๋ฅด๋ฉด page_viewed๋ฅผ ์„ ํƒํ–ˆ์„ ๋•Œ class_id, page_path, tab_viewed, scroll์ด๋ž€ ์†์„ฑ๋“ค์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์†์„ฑ๋“ค์€ 'MixpanelProperties' ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ง€์ •๋˜์–ด ์žˆ๋Š”๋ฐ์š”. ์‚ฌ์‹ค MixpanelProperties ๋Š” 50๊ฐœ๊ฐ€ ๋„˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ์„œ ํ•„์š”ํ•œ ์†์„ฑ์„ ์„ ํƒํ•ด์•ผ ํ–ˆ์—ˆ๋Š”๋ฐ์š” ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์ธ Pick์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

type PAGE_VIEWED_PROPERTIES = Pick< MixpanelProperties, "class_id" | "page_path" | "tab_viewed" | "scroll" >;

์ด์   PAGE_VIEWED_PROPERTIES ๋Š” page_viewed๋ผ๋Š” ์ด๋ฒคํŠธ๋„ค์ž„์ด ์žˆ์„ ๋•Œ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

// ์กฐ๊ฑด๋ถ€ ํƒ€์ž… ์˜ˆ์‹œ type EventProperties<T extends UnionMixpanelEventName> = T extends "page_viewed" ? PAGE_VIEWED_PROPERTIES : T extends "button_clicked" ? BUTTON_CLICKED_PROPERTIES : T extends "sign_up" ? SIGN_UP_PROPERTIES : // ... ๋‚˜๋จธ์ง€ ์ด๋ฒคํŠธ ์œ ํ˜•์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ never;

์กฐ๊ฑด๋ถ€ ํƒ€์ž…์€ ์ด๋ ‡๊ฒŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋˜ ์‚ผํ•ญ์—ฐ์‚ฐ์ž๋ฅผ ํ†ตํ•ด ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

MixpanelPropertyMapper ๋Š” T ์ฆ‰ ์ด๋ฒคํŠธ ํƒ€์ž…์ด ํ˜„์žฌ ์–ด๋–ค ์ด๋ฒคํŠธ ํƒ€์ž…์ด ์˜ฌ์ง€๋Š” ๋ชจ๋ฅด์ง€๋งŒ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ์ด๋ฒคํŠธ ํƒ€์ž…์— ํ•ด๋‹นํ•˜๋Š” ์†์„ฑ๋“ค์€ ์–ด๋–ค ๊ฒƒ์„ ๋ณด์—ฌ์ค„์ง€๋ฅผ ์ •ํ•˜๋Š” ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

T extends "page_viewed" ? PAGE_VIEWED_PROPERTIES : ...

์ด ๋ถ€๋ถ„์€ ๋งŒ์•ฝ T ์ฆ‰ ์ด๋ฒคํŠธํƒ€์ž…์ด page_viewed`` ๊ฐ™๋‹ค๋ฉด, ๊ฒฐ๊ณผ ํƒ€์ž…์€ PAGE_VIEWED_PROPERTIES` ๋ฉ๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธก์—์„œ์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•œ๋ฒˆ ๋ณด์ฃ  .

Alt text

์˜๋„ํ•œ๋Œ€๋กœ ์ด๋ฒคํŠธํƒ€์ž…์— ๋งž์ถ˜ properties๋“ค์ด ๋‚˜์™”์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์›ํ•˜๋˜ ํƒ€์ž… ์ถ”๋ก ์„ ์ด๋ค˜์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ๋ณผ๊ฒŒ์š”.

type MixpanelEventProperties< T extends UnionMixpanelEventName > = T extends MixpanelEventNames["PAGE_VIEWED"] ? PAGE_VIEWED_PROPERTIES : T extends MixpanelEventNames["BNANNER_CLICKED"] ? BANNER_CLICKED_PROPERTIES : T extends MixpanelEventNames["BUTTON_CLICKED"] ? BUTTON_CLICKED_PROPERTIES : T extends MixpanelEventNames["SIGN_UP_BEGIN"] ? SIGN_UP_BRGIN_PROPERTIES : T extends MixpanelEventNames["SIGN_UP"] ? SGIN_UP_PROPERTIES : T extends MixpanelEventNames["LOGIN"] ? LOGIN_PROPERTIES : T extends MixpanelEventNames["POP_UP"] ? POP_UP_PROPERTIES : T extends MixpanelEventNames["ORDER_BEGIN"] ? ORDER_BEGIN_PROPERTIES : T extends MixpanelEventNames["ORDER_COMPLETED"] ? ORDER_COMPLETED_PROPERTIES : T extends MixpanelEventNames["ORDER_CONTINUED"] ? ORDER_CONTINUED_PROPERTIES : T extends MixpanelEventNames["ORDER_STOP"] ? ORDER_STOP_PROPERTIES : T extends MixpanelEventNames["ORDER_CANCEL"] ? ORDER_CANCEL_PROPERTIES : T extends MixpanelEventNames["REFUND_EXCHANGE"] ? REFUND_EXCHANGE_PROPERTIES : T extends MixpanelEventNames["REVIEW_SUBMIT"] ? REVIEW_SUBMIT_PROPERTIES : T extends MixpanelEventNames["BANK"] ? BANK_PROPERTIES : T extends MixpanelEventNames["WITHDRAW"] ? WITHDRAW_PROPERTIES : T extends MixpanelEventNames["NOTIFICATION"] ? NOTIFICATION_PROPERTIES : T extends MixpanelEventNames["ADD_ACCOUNT"] ? ADD_ACCOUNT_PROPERTIES : never;

์ด ์ฝ”๋“œ ์•ž์œผ๋กœ ์™ ์ง€ ๋” ๊ธธ์–ด์งˆ ๊ฒƒ ๊ฐ™์ง€ ์•Š๋‚˜์š”? ์•„๋งˆ 1000์ค„๋„ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์„๊นŒ์š”? ์ด ๋ฐฉ์‹์€ ์ฝ”๋“œ๊ฐ€ ์ ์  ๋” ๊ธธ์–ด์ง€๊ณ  ๋ณต์žกํ•ด์ง€๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๊ฐ€ ์ค‘์ฒฉ๋˜๋ฉด์„œ ๊ฐ€๋…์„ฑ์ด ํฌ๊ฒŒ ๋–จ์–ด์กŒ์ฃ . ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, ์ข€ ๋” ์ต์ˆ™ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•œ ๊ตฌ์กฐ๋กœ ์ ‘๊ทผํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €ํฌ๋Š” ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ํ™œ์šฉํ•œ ๊ตฌ์กฐ๋กœ ์ „ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

interface MixpanelEventProperties { page_viewed: PAGE_VIEWED_PROPERTIES; button_clicked: BUTTON_CLICKED_PROPERTIES; // ... ์ถ”๊ฐ€ ์ด๋ฒคํŠธ ์†์„ฑ ๋งคํ•‘ } type MixpanelPropertyMapper<T extends keyof MixpanelEventProperties> = MixpanelEventProperties[T];

์ด ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ๊ฐ ์ด๋ฒคํŠธ ์ด๋ฆ„์— ๋Œ€ํ•œ ์†์„ฑ ํƒ€์ž…์ด MixpanelEventProperties ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด์—์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  MixpanelPropertyMapper ํƒ€์ž…์€ ์ด ๋งคํ•‘์„ ์ง์ ‘ ํ™œ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋กœ์จ ๋ณต์žกํ•œ ์‚ผํ•ญ ์—ฐ์‚ฐ์ž์™€ ์ค‘์ฒฉ ์กฐ๊ฑด๋ฌธ์„ ๋ฒ—์–ด๋‚˜ ํ›จ์”ฌ ๋ช…ํ™•ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ๊ฐ–์ถ”๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

type MixpanelPropertyMapper<T extends keyof MixpanelEventProperties> = MixpanelEventProperties[T];

์ด ํƒ€์ž…๊ตฌ์กฐ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ์ƒ์„ธํžˆ ๋‚˜์—ดํ•ด ๋ณผ๊ฒŒ์š”.

MixpanelPropertyMapper๋Š” ์ œ๋„ค๋ฆญ ํƒ€์ž… T๋ฅผ ๋ฐ›์•„, ํ•ด๋‹นํ•˜๋Š” ์ด๋ฒคํŠธ์˜ ์†์„ฑ ํƒ€์ž…์„ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์šฉ์ดํ•˜๊ฒŒ ํ•˜๋ฉฐ, ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ ํƒ€์ž…์ด ์ถ”๊ฐ€๋  ๋•Œ๋งˆ๋‹ค ์‰ฝ๊ฒŒ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋”๋ถˆ์–ด Mapped Type ์€ ๊ธฐ์กด์˜ ๊ฐ์ฒด ํƒ€์ž…์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ๊ฐ ์†์„ฑ์˜ ํƒ€์ž…์„ ๋ณ€ํ˜•ํ•˜๊ธฐ๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ์‰ฝ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ๊ธฐ์กด์˜ ๊ฐ์ฒด ํƒ€์ž…์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ๊ฐ ์†์„ฑ์˜ ํƒ€์ž…์„ ๋ณ€ํ˜•ํ•˜๊ธฐ ์‰ฌ์›€.

์˜ˆ๋ฅผ ๋“ค์–ด BUTTON_CLICKED_PROPERTIES ๊ฐ€ ์ด๋ฏธ ์žˆ์ง€๋งŒ ์–ด๋–ค ์ด์œ ์— button_clicked ๋ผ๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋“ค์–ด์™”๋‹ค๋ฉด, ๊ธฐ์กด์˜ BUTTON_CLICKED_PROPERTIES๋ฅผ ์“ฐ๋Š”๊ฒŒ ์•„๋‹Œ SpecialButtonClickedProperties ๋ผ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์ •์˜ํ•ด ๋‘” ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•˜๋Š”๊ฑฐ์ฃ . ์ด๋Ÿด ๊ฒฝ์šฐ ๋‹ค๋ฅธ ๊ฑด ๋ณ€๊ฒฝ์„ ํ•ด๋„ ์ด๋ฒคํŠธ ํƒ€์ž…๊ณผ ์†์„ฑ์„ ๋ฏธ๋ฆฌ ๋งคํ•‘ํ•ด๋‘” MixpanelEventProperties interface๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์ ์ด ์œ ์ง€๋ณด์ˆ˜ ๋ฉด์—์„œ ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”.

type SpecialButtonClickedProperties= { "classId":string } type SpecialEventPropertiesMap = { [T in keyof MixpanelEventProperties]: T extends "button_clicked" ? SpecialButtonClickedProperties : MixpanelEventProperties[T]; };

๋งˆ์น˜๋ฉฐ

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ์ปจ๋””์…”๋„ํƒ€์ž…, ์ œ๋„ค๋ฆญ, never์˜ ์กฐํ•ฉ์„ ํ†ตํ•ด ์–ป์€ ์„ฑ๊ณผ์™€ ๋ณ€ํ™”๋ฅผ ์ •๋ฆฌํ•ด ๋ณด์•˜์–ด์š”.

  • ์ œ๋„ค๋ฆญ๊ณผ extends์˜ ์กฐํ•ฉ์œผ๋กœ ์ด๋ฒคํŠธ์— ์˜ฌ์ˆ˜ ์žˆ๋Š” ์†์„ฑ๊ฐ’์„ ์ œํ•œํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ๋งˆ์ผ€ํŒ…ํŒ€์—์„œ ์ œ์‹œํ•œ ์ธก์ • ์š”์†Œ ์™ธ์˜ ๋‹ค๋ฅธ ์ž˜๋ชป๋œ ์š”์†Œ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ํœด๋จผ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํƒ€์ž…์ถ”๋ก ์ด ํ›จ์”ฌ ๋ช…ํ™•ํ•ด์ง€๊ณ  ์‰ฌ์›Œ์ ธ ๊ฐœ๋ฐœ์ž์˜ ์ƒ์‚ฐ์„ฑ์ด ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์น˜๋ฉด์„œ ํƒ€์ž…์„ ํƒ์ด ์ฒ™์ฒ™ ๋‚˜์™€์ฃผ๋ฉด ์ฝ”๋“œ์น  ๋ง›์ด ๋‚˜๊ณ  ์†๋„๊ฐ€ ๋นจ๋ผ์ง€๋Š” ๊ฒฝํ—˜์„ ๊ฐ€์ ธ๋‹ค ์ฃผ๊ฑฐ๋“ ์š”!
  • single source of truth๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ถ€์„œ์™€์˜ ํ˜‘์—…์—์„œ ํŠนํžˆ๋‚˜ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋กœ ์„œ๋กœ์˜ ์—…๋ฌด๋ฅผ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด, ์ •๋ณด์˜ ์ผ๊ด€์„ฑ๊ณผ ์ •ํ™•์„ฑ์ด ํ–ฅ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋งˆ์ผ€ํŒ… ํŒ€์—์„œ ์ง„ํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž ํ–‰๋™ ๋ถ„์„๊ณผ ํ”„๋ก ํŠธ์—”๋“œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๊ฐ„์˜ ๊ฐ„๊ทน์„ ์ค„์ด๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉํ•˜๋Š” ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋Š” ๋ถ€๊ฐ€์ ์ธ ํƒ€์ž…๊ฐ€๋“œ๋ฅผ ํ• ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค! (์ฝ”๋“œ๋„ ๊น”๋”ํ•ด ์ง€๋Š” ํšจ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒ ์–ด์š”!)

๊ธ€์„ ๋ณด์‹œ๊ณ  ๋” ๋‚˜์€ ๊ฐœ์„  ๋ฐฉ์•ˆ์ด๋‚˜ ์ƒ๊ฐํ•˜์‹  ์ฝ”๋ฉ˜ํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์•„๋ž˜ ๋Œ“๊ธ€๋ž€์— ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž์— ์žˆ์–ด ๊ท€์ค‘ํ•œ ์–‘๋ถ„์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ™‚

Hi, I'm Hyunsu ๐Ÿ‘‹

Profile Image

์•ˆ๋…•ํ•˜์„ธ์š”. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ฃผํ˜„์ˆ˜์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ํ’๋ถ€ํ•˜๊ณ  ๊ฐ€์น˜ ์žˆ๋Š” ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ์ผ์— ๋ฟŒ๋“ฏํ•จ์„ ๋Š๋‚๋‹ˆ๋‹ค.

์˜ต์‹œ๋””์–ธ(Obsidian)์—์„œ ํ˜„์žฌ ๋ธ”๋กœ๊ทธ๋กœ ํ•˜๋‚˜์”ฉ ๊ธ€์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •์— ์žˆ์–ด์š”. โ˜•๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป โ›ท

Github on ViewReach Me Out