Typescript: ํด๋ž˜์Šค๊ฐ€ ๋‹ค๋ฅธ ํŒŒ๋ผ ๋ฉ”ํŠธ๋ฆญ ํด๋ž˜์Šค์—์„œ ํŒŒ๋ผ ๋ฉ”ํŠธ๋ฆญ์ด๋˜๋„๋ก ํ—ˆ์šฉ

์— ๋งŒ๋“  2014๋…„ 11์›” 19์ผ  ยท  140์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: microsoft/TypeScript

์ด๊ฒƒ์€ ์ œ๋„ค๋ฆญ์„ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ํ—ˆ์šฉํ•˜๊ธฐ์œ„ํ•œ ์ œ์•ˆ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ํŠน์ • ๋ชจ๋‚˜๋“œ ์˜ˆ์ œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ชจ๋“  ๋ชจ๋‚˜๋“œ๊ฐ€ ๋งŒ์กฑํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด

interface Monad<T<~>> {
  map<A, B>(f: (a: A) => B): T<A> => T<B>;
  lift<A>(a: A): T<A>;
  join<A>(tta: T<T<A>>): T<A>;
}

์œ ์‚ฌํ•˜๊ฒŒ, ๋ฐ์นด๋ฅดํŠธ ํŽ‘ํ„ฐ์˜ ๊ตฌ์ฒด์ ์ธ ์˜ˆ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋ชจ๋“  ๋ฐ์นด๋ฅดํŠธ ํŽ‘ํ„ฐ๊ฐ€ ๋งŒ์กฑํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธ€์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

interface Cartesian<T<~>> {
  all<A>(a: Array<T<A>>): T<Array<A>>;
}

๋งค๊ฐœ ๋ณ€์ˆ˜ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ์—ฌ๋Ÿฌ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Foo<T<~,~>> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

์ฆ‰, ํ˜•์‹ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋’ค์— ๋ฌผ๊ฒฐํ‘œ์™€ ์ž์—ฐ ๋ฐฐ์—ด์ด ์˜ฌ ๋•Œ ํ˜•์‹ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ๋‚˜๋จธ์ง€ ์„ ์–ธ์—์„œ ์ง€์ •๋œ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ œ๋„ค๋ฆญ ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉ๋˜๋„๋ก ํ—ˆ์šฉ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ผ๋ฐ˜ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ฑ„์›Œ์•ผํ•ฉ๋‹ˆ๋‹ค.

class ArrayMonad<A> implements Monad<Array> {
  map<A, B>(f: (a:A) => B): Array<A> => Array<B> {
    return (arr: Array<A>) =>  arr.map(f);
  }
  lift<A>(a: A): Array<A> { return [a]; }
  join<A>(tta: Array<Array<A>>): Array<A> {
    return tta.reduce((prev, cur) => prev.concat(cur));
  }
}

์ธ์ž์—์„œ ์ œ๋„ค๋ฆญ ์œ ํ˜•์˜ ๊ตฌ์„ฑ์„ ์ง์ ‘ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ typedef๊ฐ€ ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ์ œ๋„ค๋ฆญ ์ •์˜๋ฅผ ์ง€์›ํ•œ๋‹ค๊ณ  ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค ( ๋ฌธ์ œ 308 ์ฐธ์กฐ).

typedef Maybe<Array<~>> Composite<~> ;
class Foo implements Monad<Composite<~>> { ... }

typedef๊ฐ€ ์œ ํšจํ•˜๋ ค๋ฉด ์ •์˜์™€ ๋ณ„์นญ์˜ ๋ฐฐ์—ด์ด ์ผ์น˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Suggestion help wanted

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

HKT์˜ ์‚ฌ๊ณ  ๋ฐฉ์‹์€ ๋ณ€ํ•  ์ˆ˜ ์žˆ๊ณ , ์Šต๊ด€์€ ๊นจ์ง€๊ณ , ์žƒ์–ด๋ฒ„๋ฆฐ ์„ธ๋Œ€๋Š” ๋‹ค์‹œ ์‚ด์•„ ๋‚˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํฐ ๊ธฐ๋Šฅ์œผ๋กœ ์ƒ๊ฐํ•˜์„ธ์š”. ๋” ๋‚˜์€ ๋ง์„ ๊ณ„์† ์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ๋ง์„ ๋“ฃ์ง€ ๋ง๊ณ , ๊ทธ๋“ค์—๊ฒŒ af * g ํŽ˜๋ผ๋ฆฌ๋ฅผ์ฃผ์„ธ์š”

๋ชจ๋“  140 ๋Œ“๊ธ€

์„ฑ๊ธ‰ํ•œ ๊ฐ€์ •์€ ์•„๋‹ˆ์ง€๋งŒ ์ž˜๋ชป ์ž…๋ ฅํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋งค๊ฐœ ๋ณ€์ˆ˜ ์œ ํ˜•์—๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ด๋ฆ„์ด ํ•„์š”ํ•˜๋ฏ€๋กœ

map<A, B>(f: (x: A) => B): T<A> => T<B>;

๋ฐ˜๋ฉด์— ์ง€๊ธˆ map์€ any ์œ ํ˜• (์—ฌ๊ธฐ์„œ ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ด๋ฆ„์€ A )์—์„œ B ๊นŒ์ง€ ๋งคํผ๋ฅผ ๊ฐ€์ ธ ์˜ค๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•ด --noImplicitAny ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹ญ์‹œ์˜ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์˜๊ฒฌ์„ ์ œ์•ˆ์œผ๋กœ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

: +1 : ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ํƒ€์ž…์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ตฌ์กฐ์— ํฐ ๋ณด๋„ˆ์Šค๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ค€ ์Šน์ธ.

์šฐ๋ฆฌ๋Š”์ด ์•„์ด๋””์–ด๋ฅผ ๋งŽ์ด ์ข‹์•„ํ•˜์ง€๋งŒ ๋ชจ๋“  ์˜๋ฏธ์™€ ์ž ์žฌ์  ์ธ ์—ฃ์ง€ ์ผ€์ด์Šค๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ๊ตฌํ˜„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ 80 %์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃจ๋Š” ์ƒ˜ํ”Œ PR์ด ์žˆ์œผ๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„์— ์ •๋ง ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌผ๊ฒฐํ‘œ ๊ตฌ๋ฌธ์— ๋Œ€ํ•œ ์‚ฌ๋žŒ๋“ค์˜ ์˜๊ฒฌ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? T~2 ์˜ ๋Œ€์•ˆ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

interface Foo<T<~,~>> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

์œ ํ˜• ๋ณ„์นญ์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ณ  ์ œ๋„ค๋ฆญ์„ ์ง์ ‘ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Foo<T<~,~,~>, U<~>, V<~, ~>> {
  bar<A, B, C, D>(a: A, f: (b: B) => C, d: D): T<U<A>, V<B, C>, D>;
}

์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ๋กœ ๋‹ค๋ฅธ ๊ณณ์—์„œ๋Š” ๊ทธ๋ ‡๊ฒŒํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ช…์‹œ์ ์ธ arity๋ฅผ โ€‹โ€‹๊ฐ–๋Š” ๊ฒƒ์€ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค.

interface Foo<T<~,~>> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

์ข€ ๋” ๋ช…ํ™•ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์–ธ์–ด๋Š” ~ ๋Œ€์‹  ๋น„์Šทํ•œ ์ปจํ…์ŠคํŠธ์—์„œ * ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

interface Foo<T<*,*>> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

๊ทธ ์ ์„ ๊ทน๋‹จ์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Foo<T: (*,*) => *> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

T<~,~> ๋„ T~2 ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์ œ์•ˆ์„ ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ~ ํ•˜๋“  * ์‚ฌ์šฉํ•˜๋“  ์ƒ๊ด€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. JS ์‹๋ณ„์ž๊ฐ€ ๋  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ _ ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. => ํ‘œ๊ธฐ๋ฒ•์ด ์ œ๊ณตํ•˜๋Š” ์ด์ ์ด ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์ œ๋„ค๋ฆญ์€ ์ผ๋ถ€ ์ž…๋ ฅ ์œ ํ˜•์„ ์ทจํ•˜๊ณ  ๋‹จ์ผ ์ถœ๋ ฅ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋” ๊ฐ€๋ฒผ์šด ๊ตฌ๋ฌธ์€ ์ œ๋„ค๋ฆญ์˜ arity๋ฅผ โ€‹โ€‹์™„์ „ํžˆ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์„œ๋Š” ์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ๋ถ€ํ„ฐ ์•Œ์•„ ๋‚ด๊ณ  ๋‚˜๋จธ์ง€๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ฒŒ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์Šค ํŒŒ์ผ๋Ÿฌ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๊ฐœ๋ฐœ์ž๋ฅผ ๊ดด๋กญํžˆ๋Š” ๋ฐ ๊ถŒ์žฅ๋˜๋Š” ํฌ๋Ÿผ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋” ๋งŽ์€ ๊ด€๋ จ ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋” ํฐ ์งˆ๋ฌธ์— ๋Œ€ํ•ด ๋งŽ์€ ์ƒˆ๋กœ์šด ๋ฌธ์ œ๋ฅผ ๊ธฐ๋กํ•˜๊ฑฐ๋‚˜ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ผ๋ จ์˜ ์งˆ๋ฌธ์œผ๋กœ ์žฅ๊ธฐ ์‹คํ–‰ ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” https://gitter.im/Microsoft/TypeScript ์—์„œ ์ฑ„ํŒ…๋ฐฉ์— ์ฐธ์—ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋Œ€ํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@metaweta ์–ด๋–ค ์†Œ์‹์ด๋ผ๋„? ๋„์›€ / ํ† ๋ก ์ด ํ•„์š”ํ•˜๋ฉด์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋ธŒ๋ ˆ์ธ ์Šคํ† ๋ฐ์„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์ •๋ง ์›ํ•ฉ๋‹ˆ๋‹ค.

์•„๋‹ˆ, ์ง์žฅ์—์„œ ๋‚ด๊ฐ€ ์ผํ•ด์•ผํ–ˆ๋˜ ์ž์œ  ์‹œ๊ฐ„์„ ๋Œ€์‹ ํ–ˆ๋‹ค.

๋ฒ”ํ”„ :์ด ๊ธฐ๋Šฅ์„ ๊ณ ๋ คํ•ด ๋ณผ ๊ธฐํšŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

https://github.com/Microsoft/TypeScript/issues/1213#issuecomment -96854288์€ ์—ฌ์ „ํžˆ โ€‹โ€‹ํ˜„์žฌ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ๋Š” ๊ธฐ๋Šฅ์˜ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜์žˆ๋Š” ํ•ญ๋ชฉ์ด ์—†์Šต๋‹ˆ๋‹ค.

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

interface Database<P<~> extends PromiseLike<~>> {   
    query<T>(s:string, args:any[]): P<T> 
}

์—ฌ๊ธฐ์—๋„ ์œ ์šฉ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค http://stackoverflow.com/questions/36900619/how-do-i-express-this-in-typescript

: +1 :

HKT์˜ ์‚ฌ๊ณ  ๋ฐฉ์‹์€ ๋ณ€ํ•  ์ˆ˜ ์žˆ๊ณ , ์Šต๊ด€์€ ๊นจ์ง€๊ณ , ์žƒ์–ด๋ฒ„๋ฆฐ ์„ธ๋Œ€๋Š” ๋‹ค์‹œ ์‚ด์•„ ๋‚˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํฐ ๊ธฐ๋Šฅ์œผ๋กœ ์ƒ๊ฐํ•˜์„ธ์š”. ๋” ๋‚˜์€ ๋ง์„ ๊ณ„์† ์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ๋ง์„ ๋“ฃ์ง€ ๋ง๊ณ , ๊ทธ๋“ค์—๊ฒŒ af * g ํŽ˜๋ผ๋ฆฌ๋ฅผ์ฃผ์„ธ์š”

์˜ˆ, ๊ธฐ์กด JS ์ฝ”๋“œ๋ฒ ์ด์Šค์— ์œ ํ˜•์„ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•œ ํ›„ ์ฒ˜์Œ 15 ๋ถ„ ๋™์•ˆ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ณผ ๋•Œ๊นŒ์ง€ TS๋กœ ์ „ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ๋„์™€ ๋“œ๋ฆด๊นŒ์š”?

์ด๊ฒƒ์ด # 7848๊ณผ ์–ด๋–ค ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ๊ณ ์ฐจ ์ข…๋ฅ˜์˜ ๋‹ค๋ฅธ ์ธก๋ฉด์— ๋Œ€ํ•ด์„œ๋Š” ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@ boris-marinov Ryan Cavanaugh์˜ ๋‹ต๋ณ€์— ๋”ฐ๋ฅด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์†Œํ•œ 80 %์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃจ๋Š” ์ƒ˜ํ”Œ PR์ด ์žˆ์œผ๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„์— ์ •๋ง ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ํ•ต์‹ฌ ๊ฐœ๋ฐœ์ž๋กœ๋ถ€ํ„ฐ ๋ช‡ ๊ฐ€์ง€ ํžŒํŠธ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ PR์„ ๊ตฌํ˜„ํ•  ์‹œ๊ฐ„์ด ์žˆ์ง€๋งŒ ์ง€๊ธˆ๊นŒ์ง€๋Š” ์งˆ๋ฌธ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ ํ›Œ๋ฅญํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ง„ํ–‰ ์ƒํ™ฉ์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

@Artazor ํฌ๋ž˜ํ‚น # 7848๋„ ์‚ดํŽด ๋ณด์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ œ๋„ค๋ฆญ์„ ํฌํ•จํ•˜๋Š”์ด ๋ฌธ์ œ์˜ ๋‹ค๋ฅธ ์ธก๋ฉด์„ ์ฒ˜๋ฆฌํ•˜๊ณ  IMHO๊ฐ€ ์—†์œผ๋ฉด ๋ถˆ์™„์ „ํ•˜๊ฒŒ ๋Š๊ปด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค (์ œ๋„ค๋ฆญ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ์‹ค์ œ๋กœ ๋งŽ์€ ์œ ํ˜• ์ˆ˜์ค€ ์ฝ”๋“œ๋ฅผ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค).

์ด ์ œ์•ˆ์€ ์ •๋ง ํ›Œ๋ฅญํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. TypeScript์—์„œ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•์„ ๊ฐ€์ง€๋ฉด ํ˜„์žฌ ๊ฐ€๋Šฅํ•œ ๊ฒƒ๋ณด๋‹ค ๋” ๊ฐ•๋ ฅํ•œ ์ถ”์ƒํ™”๋ฅผ ์„ค๋ช… ํ•  ์ˆ˜์žˆ๋Š” ์ƒˆ๋กœ์šด ์ˆ˜์ค€์˜ ๊ตฌ๋ฉ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ OP์— ์ œ๊ณต๋œ ์˜ˆ์ œ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ค„์˜ A

class ArrayMonad<A> implements Monad<Array> {

๋ชจ๋‘ ๊ณ ์œ  ํ•œ ์ผ๋ฐ˜ A ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋ฉ”์„œ๋“œ์—์„œ๋„ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ map ๋ฅผ this ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋กœ map ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์–ด๋–ค ๋ชจ์Šต์ผ๊นŒ์š”? ์•„๋งˆ ์ด๋ ‡๊ฒŒ?

interface Functor<T, A> {
  map<B>(f: (a: A) => B): T<A> => T<B>;
}

class Maybe<A> implements Functor<Maybe, A> {
  ...
}

@paldepind # 7848์„ ํ™•์ธํ•˜์„ธ์š”. IMHO ์ด๊ฒƒ๊ณผ ๊ทธ ํ•˜๋‚˜๊ฐ€ ์ •๋ง๋กœ ๋‹จ์ผ PR๋กœ ๋ณ‘ํ•ฉ๋˜์–ด์•ผํ•˜์ง€๋งŒ, ๊ทธ ๋…ผ์˜๋Š” ๊ทธ ํŠน์ •ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌผ๊ฑด์€ ์–ธ์ œ ์ฐฉ๋ฅ™ํ• ๊นŒ์š”? ๊ทธ๊ฒƒ์€ ์ผ์ข…์˜ ํ•„์ˆ˜์ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

interface SomeX<X, T> {
   ...// some complex definition
  some: X<T>
}

interface SomeA<T> extends SomeX<A, T> {
}

?

@whitecolor ๋‚˜๋Š” ์ง€๊ธˆ ๋” ํฐ ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ํŠ€๊ธธ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ, ๋” ๋†’์€ ์šฐ์„  ์ˆœ์œ„๋ฅผ

  1. TypeScript 2.0 RC๋Š” 2 ์ฃผ ์ „์— ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ž์ฒด๋กœ ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.
  2. ๋„ค์ดํ‹ฐ๋ธŒ JS ํ•จ์ˆ˜ ์ธ bind , call ๋ฐ apply ๋Š” ํ˜•์‹์ด ์ง€์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ๊ฐ€๋ณ€ ์ œ๋„ค๋ฆญ ์ œ์•ˆ ์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. Object.assign ๋„ ๋น„์Šทํ•œ ์ˆ˜์ •์ด ํ•„์š”ํ•˜์ง€๋งŒ ๊ฐ€๋ณ€ ์ œ๋„ค๋ฆญ๋งŒ์œผ๋กœ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  3. Lodash์˜ _.pluck , Backbone ๋ชจ๋ธ์˜ get ๋ฐ set ๋ฉ”์„œ๋“œ ๋“ฑ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜ ๋ฏธ๋ž˜์˜ React ์—๋„

๋‚ด๊ฐ€์ด ๊ธฐ๋Šฅ์„ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ (๋‚˜๋Š” ๊ทธ๋Ÿฐ ๊ธฐ๋Šฅ์„ _ ์ข‹์•„ํ•  ๊ฒƒ์ด๋‹ค _) ๊ณง ์ถœ์‹œ ๋  ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š๋‹ค.

ํ—‰ํ—‰
์„ค๋ช…ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ, ๋ชฉ๋ก์˜ ์„ธ ๋ฒˆ์งธ ํ•ญ๋ชฉ์€ https://github.com/Microsoft/TypeScript/issues/1295๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์–ด๋–ป๊ฒŒ ๋“  2.1dev์—์„œ ํ˜„์žฌ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋™์˜ํ•œ๋‹ค. ๋ฐ”๋ผ๊ฑด๋Œ€ ๊ทธ๊ฒƒ์€ ๊ทธ๊ฒƒ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(์ด ๋ฌธ์ œ๊ฐ€ ์›ํ•˜๋Š” ๋žญํฌ 2 ๋‹คํ˜•์„ฑ์€
Fantasy Land ์‚ฌ์šฉ์ž๋Š” ํ•ด๋‹น ์‚ฌ์–‘ ๋‚ด์—์„œ ๋‹ค์–‘ํ•œ ADT๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
Ramda๋Š” ์ด๊ฒƒ์„ ์ƒ๋‹นํžˆ ํ•„์š”๋กœํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค.)

2016 ๋…„ 9 ์›” 6 ์ผ ํ™”์š”์ผ 11:00 Alex [email protected] ์ž‘์„ฑ :

@isiahmeadows https://github.com/isiahmeadows
์„ค๋ช…ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋„ค, ๋ชฉ๋ก์˜ ์„ธ ๋ฒˆ์งธ ํ•ญ๋ชฉ์€ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
# 1295 https://github.com/Microsoft/TypeScript/issues/1295 ๋Œ€๊ธฐ ์ค‘
๋„ˆ๋ฌด.

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์–ด๋–ป๊ฒŒ ๋“  2.1dev์—์„œ ํ˜„์žฌ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/Microsoft/TypeScript/issues/1213#issuecomment -244978475,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AERrBMvxBALBe0aaLOp03vEvEyokvxpyks5qnX_8gaJpZM4C99VY
.

์ด ๊ธฐ๋Šฅ์€ ๋ฐ˜์‘ ์–‘์‹์„ ์ •์˜ํ•˜๋Š” ๋ฐ ๋งŽ์€ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด struct๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Model {
  field1: string,
  field2: number,
  field3?: Model
}

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ ๋œ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Handler<T> {
  readonly value: T;
  onChange: (newValue: T) => void;
}

์ด ํ•ธ๋“ค๋Ÿฌ๋Š” React ์ปดํฌ๋„ŒํŠธ์— ์†Œํ’ˆ์œผ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋™์ผํ•œ ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ๊ฐ’ ๋Œ€์‹  ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

function makeForm(value: Model): {
  field1: Handler<string>,
  field2: Handler<number>,
  field3: Handler<Model>,
}

ํ˜„์žฌ๋กœ์„œ๋Š” TS๊ฐ€ ๋‹ค๋ฅธ ์œ ํ˜•์˜ ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ํ˜•์„ ์ƒ์„ฑ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Cow HKT๋กœ makeForm ๋ฅผ ์ž…๋ ฅ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

ํ , ํฅ๋ฏธ ๋กญ๊ตฐ์š”.

์•„๋งˆ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์ด ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

//Just a container
interface Id <A> {
  value: A
}

interface Model <T> {
  field1: T<string>,
  field2: T<number>,
  field3?: T<Model>
}

makeForm (Model<Id>): Model<Handler>

@ boris-marinov ๊ฐ€์žฅ ํฅ๋ฏธ๋กœ์šด ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

interface Model<T> {
  //...
  field3?: T<Model> // <- Model itself is generic.
                    // Normally typescript will error here, requiring generic type parameter.
}

HKT๊ฐ€ ์†Œ์œ„ ๋ถ€๋ถ„ ์œ ํ˜• (https://github.com/Microsoft/TypeScript/issues/4889#issuecomment-247721155)์— ๋Œ€ํ•œ ๋‹ต์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์–ธ๊ธ‰ ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

type MyDataProto<K<~>> = {
    one: K<number>;
    another: K<string>;
    yetAnother: K<boolean>;
}
type Identical<a> = a;
type Optional<a> = a?; // or should i say: a | undefined;
type GettableAndSettable<a> = { get(): a; set(value: a): void }

type MyData = MyDataProto<Identical>; // the basic type itself
type MyDataPartial = MyDataProto<Optional>; // "partial" type or whatever you call it
type MyDataProxy = MyDataProto<GettableAndSettable>; // a proxy type over MyData
// ... etc

์ข€ ๋น ์ง€๋Š”. {x: number?} ๋Š” {x?: number} ํ• ๋‹น ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

2016 ๋…„ 10 ์›” 11 ์ผ ํ™”์š”์ผ 09:16 Aleksey Bykov [email protected] ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

HKT๊ฐ€ ์†Œ์œ„
๋ถ€๋ถ„ ์œ ํ˜• (# 4889 (์ฃผ์„))
https://github.com/Microsoft/TypeScript/issues/4889#issuecomment-247721155
) :

MyDataProto ์œ ํ˜• ํ•˜๋‚˜ : K;
๋‹ค๋ฅธ : K;
yetAnother : K;
} ์œ ํ˜• ๋™์ผ = a; ์œ ํ˜• ์„ ํƒ = a ?;
= {get () : a;

;
;
;

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/Microsoft/TypeScript/issues/1213#issuecomment -252913109,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AERrBNFYFfiW01MT99xv7UE2skQ3qiPMks5qy4wRgaJpZM4C99VY
.

@isiahmeadows ๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์†์„ฑ์„ ์œ ํ˜•์— ๋”ฐ๋ผ ์„ ํƒ ์‚ฌํ•ญ์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• / ๊ตฌ๋ฌธ์ด ์—†์Šต๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ํ•˜๋‚˜ : ์žฌ์‚ฐ์„ readonly ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋งคํฌ๋กœ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ƒฅ์ด ๋ฐ–์œผ๋กœ ๋˜์ง€๊ธฐ ... ๋‚ด๊ฐ€ ์„ ํ˜ธ * ์˜ค๋ฒ„ ๊ตฌ๋ฌธ ~ ๊ตฌ๋ฌธ์„. ~์— ๋Œ€ํ•œ ๋ฌด์–ธ๊ฐ€๋Š” ํ‚ค๋ณด๋“œ ๋ ˆ์ด์•„์›ƒ ๊ด€์ ์—์„œ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด์œ ๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ *๊ฐ€ ํ˜ผํ•ฉ ๋œ ๋ชจ๋“  ๊บพ์‡  ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด *๊ฐ€ ์ข€ ๋” ์ฝ๊ธฐ ์‰ฝ๊ณ  ๊ตฌ๋ณ„ํ•˜๊ธฐ ์‰ฌ์šด ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋งํ•  ๊ฒƒ๋„์—†์ด Haskell๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ์–ธ์–ด์— ์ต์ˆ™ํ•œ ์‚ฌ๋žŒ๋“ค์€ ์ฆ‰์‹œ ๊ตฌ๋ฌธ์„ HKT์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ข€ ๋” ์ž์—ฐ์Šค๋Ÿฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค.

* ๊ตฌ๋ฌธ์— ๋™์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ฒซ์งธ, ๋” ๊ตฌ๋ณ„ํ•˜๊ธฐ ์‰ฝ๊ณ 
๋‘˜์งธ, "๋ชจ๋“  ์œ ํ˜•์ด ์ž‘๋™ํ•˜๋Š”"์œ ํ˜•์„ ๋” ์ž˜ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.


Isiah Meadows
[email protected]

2016 ๋…„ 11 ์›” 6 ์ผ ์ผ์š”์ผ ์˜ค์ „ 12์‹œ 10 ๋ถ„, Landon Poch [email protected]
์ผ๋‹ค :

๊ทธ๋ƒฅ ๋˜์ ธ ๋ฒ„๋ฆฌ๋ฉด ... ๋‚˜๋Š” ~ ๊ตฌ๋ฌธ๋ณด๋‹ค * ๊ตฌ๋ฌธ์„ ์„ ํ˜ธํ•œ๋‹ค.
~์— ๋Œ€ํ•œ ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ‚ค๋ณด๋“œ ๋ ˆ์ด์•„์›ƒ์—์„œ ๋„ˆ๋ฌด ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์›๊ทผ๋ฒ•. ๋˜ํ•œ ์ด์œ ๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ *๊ฐ€ ์ข€ ๋”
๋ฏน์Šค์—์žˆ๋Š” ๋ชจ๋“  ๊บพ์‡  ๊ด„ํ˜ธ๋กœ ์ฝ๊ธฐ / ๊ตฌ๋ณ„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋งํ•  ๊ฒƒ๋„์—†์ด Haskell๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ์–ธ์–ด์— ์ต์ˆ™ํ•œ ์‚ฌ๋žŒ๋“ค์€
๊ตฌ๋ฌธ์„ HKT์— ์ฆ‰์‹œ ์—ฐ๊ฒฐํ•˜์‹ญ์‹œ์˜ค. ์ข€ ๋” ์ž์—ฐ์Šค๋Ÿฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/Microsoft/TypeScript/issues/1213#issuecomment -258659277,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AERrBHQ4SYeIiptB8lhxEAJGOYaxwCkiks5q7VMvgaJpZM4C99VY
.

๋งˆ์ผ์Šคํ†ค : community ? ์ด ๋ฌธ์ œ / ๊ธฐ๋Šฅ์˜ ํ˜„์žฌ ์ƒํƒœ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@whitecolor ์ƒํƒœ๋Š” DIY์ž…๋‹ˆ๋‹ค (์Šค์Šค๋กœํ•˜์‹ญ์‹œ์˜ค)

๋ฌธ์ œ์— Accepting PRs ๋ ˆ์ด๋ธ”์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์œ„ํ•œ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ํ™˜์˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ https://github.com/Microsoft/TypeScript/wiki/FAQ#what -do-the-labels-on-these-issues-mean์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

https://github.com/Microsoft/TypeScript/issues/1213#issuecomment -96854288๋„ ์ฐธ์กฐ

์ข‹์•„, ๋‚˜๋Š” ๋ ˆ์ด๋ธ”์„ ๋ด…๋‹ˆ๋‹ค. ๋น„ TS ํŒ€์ด ๊ทธ๊ฒƒ์„ ๋‹ฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์˜์‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ํ•ต์‹ฌ ๊ฐœ๋ฐœ์ž๋กœ๋ถ€ํ„ฐ ๋ช‡ ๊ฐ€์ง€ ํžŒํŠธ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ PR์„ ๊ตฌํ˜„ํ•  ์‹œ๊ฐ„์ด ์žˆ์ง€๋งŒ ์ง€๊ธˆ๊นŒ์ง€๋Š” ์งˆ๋ฌธ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ ํ›Œ๋ฅญํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ง„ํ–‰ ์ƒํ™ฉ์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

@Artazor ๋‹น์‹ ์€ ์ด๊ฒƒ์— ์–ด๋–ค ์šด์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@raveclassic- ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ค์›Œ์กŒ์ง€๋งŒ ์•ž์œผ๋กœ ๋‚˜์•„๊ฐˆ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ตฌ๋ฌธ ์ ์œผ๋กœ๋Š” ๋ถ„๋ช…ํ•˜์ง€๋งŒ typechecking ๊ทœ์น™ / ๋‹จ๊ณ„๋Š” ๋‚ด๊ฐ€ ์›ํ•˜๋Š”๋งŒํผ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.-)

๋‚ด ํ™œ๋™์„ ๋˜ ์‚ด๋ฆฌ์ž-)

์ง„ํ–‰ ์ƒํ™ฉ๊ณผ ์•„์ด๋””์–ด ๊ฐœ๋ฐœ ๊ฒฝ๋กœ๋ฅผ ์ถ”์ ํ•˜๊ธฐ ๋งŒํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ธ ๊ฐ€์ง€ ์˜ต์…˜์„ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค.

์„ ํƒ์  higherShape ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ TypeParameterDeclaration ์„ (๋ฅผ) ๋ณด๊ฐ• ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค.

    export interface TypeParameterDeclaration extends Declaration {
        kind: SyntaxKind.TypeParameter;
        name: Identifier;
        higherShape?: HigherShape // For Higher-Kinded Types <--- this one 
        constraint?: TypeNode;

        // For error recovery purposes.
        expression?: Expression;
    }

HigherShape ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜์žˆ๋Š” ์„ธ ๊ฐ€์ง€ ์˜ต์…˜์„ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค.

1. ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ๋‹จ์ˆœ Arity

type HigherShape = number

๋‹ค์Œ ์‚ฌ์šฉ๋ฒ•์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

class Demo<Wrap<*>, WrapTwo<*,*>> {   // 1 and 2
    str: Wrap<string>;
    num: Wrap<number>;
    both: WrapTwo<number, string>;
}

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

var x: Demo<Array, Demo>

๊ทธ๋Ÿฐ ๋‹ค์Œ .both ์†์„ฑ์œผ๋กœ ์ง€์—ฐ๋œ ์œ ํ˜• ๊ฒ€์‚ฌ ๋ฌธ์ œ์™€ ์‹ธ์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ number ์œ ํ˜•์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ Demo ์œ ํ˜•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณ ์ฐจ ํ˜•ํƒœ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

(* => *, (*,*) => *) => *

2. ์™„์ „ํžˆ ๊ตฌ์กฐํ™” ๋œ ๋„๋ฉ”์ธ ๋ฐ ๊ณต๋™ ๋„๋ฉ”์ธ

๊ทธ๋Ÿฐ ๋‹ค์Œ ์•ž์„œ ์–ธ๊ธ‰ ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ชจ์–‘์„ ํ‘œํ˜„ํ•  ์ˆ˜์žˆ๋Š” ๋” ๋†’์€ ๋ชจ์–‘์˜ ๋ฐ˜๋Œ€, ๊ฐ€์žฅ ์™„์ „ํ•œ ํ‘œํ˜„์„ ์กฐ์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

(* => (*,*)) => ((*,*) => *)

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

3. ๊ตฌ์กฐํ™” ๋œ ๋„๋ฉ”์ธ / ์•”์‹œ ์  ๋‹จ์ˆœ ๊ณต๋™ ๋„๋ฉ”์ธ

์ฃผ์š” ์•„์ด๋””์–ด-์œ ํ˜• ํ‘œํ˜„์‹ (์‹ค์ œ ์œ ํ˜• ์ธ์ˆ˜ ํฌํ•จ)์€ ํ•ญ์ƒ ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ์ ‘์ง€ ์œ ํ˜•์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— ๊ฐ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ˜•์‹์œผ๋กœ ๊ณ ์œ  ํ•œ ์„ธ๋ถ€ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ œ๊ฐ€ ์˜นํ˜ธํ•˜๋ ค๋Š” ์ตœ์ข… ๊ฒฐ์ •์ด์—ˆ์Šต๋‹ˆ๋‹ค.

type HigherShape = NodeArray<TypeParameterDeclaration>;

์˜ˆ:

class A {x: number}
class A2 extends A { y: number }
class Z<T> { z: T; }

class SomeClass<T1<M extends A> extends Z<M>, T2<*,*<*>>, T3<* extends string>> {
        var a: T1<A2>; // checked early
        var b: T2<string, T1>; // second argument of T2 should be generic with one type parameter  
        var c: T3<"A"|"B">; // not very clever but it is checked
        // ...
        test() {
             this.a.z.y = 123 // OK
             // nothing meaningful can be done with this.b and this.c
        }
}

์—ฌ๊ธฐ์—์„œ M ๋Š” T1<M extends A> extends Z<M> ๋Œ€ํ•ด ๋กœ์ปฌ์ด๋ฉฐ T1๋ณด๋‹ค ๋” ๊นŠ์€ ๊ฐ€์‹œ์„ฑ ๋ฒ”์œ„์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ M ๋Š” SomeClass ๋ณธ๋ฌธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  * ๋Š” ์–ด๋–ค ๊ฒƒ๊ณผ๋„ ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š” (๋‚˜์ค‘ ๋‹จ๊ณ„์—์„œ ๊ตฌํ˜„ ๋  ์ˆ˜์žˆ๋Š”) ์ƒˆ๋กœ์šด ์‹๋ณ„์ž (์ต๋ช… ์œ ํ˜•)๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.


๋”ฐ๋ผ์„œ TypeParameterDeclaration์˜ ์ตœ์ข… ์„œ๋ช…์€

    export interface TypeParameterDeclaration extends Declaration {
        kind: SyntaxKind.TypeParameter;
        name: Identifier;
        typeParameters?: NodeArray<TypeParameterDeclaration> // !!! 
        constraint?: TypeNode;

        // For error recovery purposes.
        expression?: Expression;
    }

@DanielRosenwasser , @ aleksey-bykov, @isiahmeadows ๋“ฑ์˜ ์˜๊ฒฌ์„ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค-)

๋‚˜์—๊ฒŒ ๊ดœ์ฐฎ์•„ ๋ณด์ด์ง€๋งŒ TypeScript ์ฝ”๋“œ ๊ธฐ๋ฐ˜์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ์— ๋Œ€ํ•ด ๊ฑฐ์˜ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

ํ•ฉ์ฐฝ๋‹จ์— ์ œ ๋ชฉ์†Œ๋ฆฌ๋ฅผ ๋” ํ•ด์ฃผ์‹œ๊ณ  ์‘์›ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค, Artazor! :)

์ด ๊ธฐ๋Šฅ์€ Redux๋ฅผ ํ˜•์‹ ์•ˆ์ „์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ตฌํ˜„์— ์œ ์šฉ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@michaeltontchev Redux ํ˜•์‹ ์•ˆ์ „์„ ๋งŒ๋“œ๋Š” ๋ฐ ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ด€์‹ฌ์ด ์žˆ์œผ์‹œ๋ฉด ์ตœ๊ทผ์— Redux ๋ฐ EventEmitter์˜ ์•„์ด๋””์–ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ https://github.com/bcherny/tdux ๋ฐ https://github.com/bcherny/typed-rx-emitter๋ฅผ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๊ธฐ๋ณธ ์ผ๋ฐ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ @rbuckton ๋ธŒ๋žœ์น˜ # 13487๋กœ ๋ฆฌ๋ฒ ์ด์Šคํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” ์šฐ๋ฆฌ๊ฐ€ ํฌ๊ฒŒ ์ถฉ๋Œ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@bcherny- ๋งํฌ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

๋‚˜๋Š” ์ƒํƒœ์˜ ๋ชจ๋“  ์†์„ฑ์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜•์˜ ๊ฐ์†๊ธฐ๋ฅผ (์ถ”๊ฐ€ ์‚ฌํ•ญ ์—†์Œ) ๋ณด์žฅํ•˜์—ฌ combineReducers๋ฅผ ์œ ํ˜• ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠน์ • ๊ฒฝ์šฐ์— ์ค‘์ฒฉ ๋œ ์ œ๋„ค๋ฆญ์—†์ด ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์ค‘์ฒฉ ๋œ ์†”๋ฃจ์…˜์ด ๋” ์ข‹์•˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

import { combineReducers, Reducer } from 'redux';

interface IState {
    // my global state definition
}

type StatePropertyNameAndTypeAwareReducer\<S> = {
    [P in keyof S]: Reducer<S[P]>;
};

let statePropertyToReducerMap : StatePropertyNameAndTypeAwareReducer<IState> = {
    navBarSelection: navBarReducer,
};

let combinedReducers = combineReducers<IState>(statePropertyToReducerMap);

๊ธฐ๋ณธ์ ์œผ๋กœ ์œ„์—์„œ ์†Œ๊ฐœ ํ•œ ์œ ํ˜•์€ combineReducers์— ์ „๋‹ฌํ•˜๋Š” ๊ฐ์†๊ธฐ ๋งคํ•‘์ด ์ƒํƒœ์˜ ๋ชจ๋“  ์†์„ฑ์„ ํฌํ•จํ•˜๊ณ  ์ ์ ˆํ•œ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ๊ฐ–๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์˜จ๋ผ์ธ ๊ฒ€์ƒ‰ ์ค‘์— ๊ทธ๋Ÿฐ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค-๋‘ ๋‹ฌ ์ „์— ๋‚˜์˜จ keyof ๊ธฐ๋Šฅ ์—†์ด๋Š” ํ•  ์ˆ˜์—†๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. :)

keyof ๊ธฐ๋Šฅ์€ ImmutableJs๋ฟ๋งŒ ์•„๋‹ˆ๋ผ setter์™€ getter๋ฅผ ํ˜•์‹์— ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐ ์œ ์šฉ ํ•  ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ, ์—ฌ์ „ํžˆ ์ถ”๊ฐ€ ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด ์ค‘์ฒฉ ๋œ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด StatePropertyNameAndTypeAwareReducer ์œ ํ˜•์—์„œ Reducer ์œ ํ˜•์„ ํ•˜๋“œ ์ฝ”๋”ฉ ํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ์ง€๋งŒ ๋Œ€์‹  ์ œ๋„ค๋ฆญ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ค‘์ฒฉ ์ œ๋„ค๋ฆญ์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ˆœ๊ฐ„.

Edit2 : ์—ฌ๊ธฐ์— Redux์— ๋Œ€ํ•œ ์ด์Šˆ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค : https://github.com/reactjs/redux/issues/2238 ๊ทธ๋“ค์ด TypeScript๋ฅผ ๋งŽ์ดํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋ฏ€๋กœ Redux๋ฅผ ์•„๋Š” TypeScript ์‚ฌ๋žŒ๋“ค์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์ง€๋‚ด์š”?

์ˆœ์ง„ํ•œ ์งˆ๋ฌธ ์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์™œ ์ผ๋ฐ˜ ์ผ๋ฐ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋Œ€์‹  ~ ๋˜๋Š” * ์ž…๋‹ˆ๊นŒ? ๋ฏธ์‚ฌ์šฉ์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ? ์ฆ‰. ์™œ ์•ˆ๋ผ :

type Functor<A<T>> = {
  map(f: (value: T) => U): A<U>
}

๋˜๋Š”:

kind Functor<A<T>> = {
  map(f: (value: T) => U): A<U>
}

๋˜๋Š”:

abstract type Functor<A<T>> = {
  map(f: (value: T) => U): A<U>
}

@bcherny Functor<A<T>> ์ด์ „์—๋Š” " A of T "๋ฅผ ์˜๋ฏธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌ๋ฌธ์— ๋ชจํ˜ธํ•จ์ด ์ƒ๊ฒผ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. T ๋Š” ์ง€์—ญ์˜ ์ผ๋ถ€ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. ๋ฒ”์œ„. ๊ทธ๋Ÿด ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š์ง€๋งŒ ๊ฐ™์€ ์ด์œ ๋กœ์ด ๊ตฌ๋ฌธ์€ ์ผ๋ถ€ ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@masaeedu ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค . ์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์€ "ํ˜„์žฌ ๋ฒ”์œ„์—์„œ ์—„๊ฒฉํ•˜๊ฒŒ T ๋ฐ”์ธ๋”ฉ"์ด ์•„๋‹ˆ๋ผ " T ๋Š๋ฆฌ๊ฒŒ ๋ฐ”์ธ๋”ฉ"์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, T: * => * ๋Œ€ํ•œ @DanielRosenwasser ์˜ ์ œ์•ˆ์ด ์—ฌ๊ธฐ์—์„œ ๊ฐ€์žฅ ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. "์„ ํ–‰ ๊ธฐ์ˆ "์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Haskell์—์„œ -> ์—ฐ์‚ฐ์ž๋Š” ์‹ค์ œ๋กœ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™” ๋œ ์œ ํ˜•์ž…๋‹ˆ๋‹ค (์•„๋งˆ๋„ Func<TArg, TRet> ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค). ํƒ€์ž… ์ƒ์„ฑ์ž -> ์ž„์˜์˜ ๋‘ ๊ฐ€์ง€ ์œ ํ˜•์„ ์ˆ˜์šฉ T ๋ฐ U ๋ฐ ์œ ํ˜•์˜ ๊ฐ’์— ๋งคํ•‘๋˜๋Š” ๊ฐ’ ์ƒ์„ฑ์ž (์ฆ‰ ํ•จ์ˆ˜)์˜ ์œ ํ˜• ์ƒ์„ฑ T ํ–‰์„ U ์œ ํ˜•์˜ ๊ฐ’.

ํฅ๋ฏธ๋กœ์šด ๊ฒƒ์€ ๊ทธ๊ฒƒ์ด ๋˜ํ•œ ์นœ์ ˆํ•œ ์ƒ์„ฑ์ž๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์ข…๋ฅ˜ ์ƒ์„ฑ์ž -> ๋Š” ๋‘ ๊ฐ€์ง€ ์ž„์˜ ์ข…๋ฅ˜ T* ๋ฐ U* (์‹œ๊ฐ์  ๊ตฌ๋ถ„์„์œ„ํ•œ ๋ณ„ํ‘œ)๋ฅผ ํ—ˆ์šฉํ•˜๊ณ  ์ข…๋ฅ˜ T* ์ข…๋ฅ˜๋ฅผ ๋งคํ•‘ํ•˜๋Š” ์ข…๋ฅ˜์˜ ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. U* .

์ด ์‹œ์ ์—์„œ ํŒจํ„ด์„ ๋ฐœ๊ฒฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ํ˜•์„ ์ •์˜ํ•˜๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ตฌ๋ฌธ๊ณผ ์˜๋ฏธ๋Š” ๋‹จ์ˆœํžˆ ์œ ํ˜•์„ ์ •์˜ํ•˜๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋ฐ ์žฌ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ๊ทธ๊ฒƒ์€ ์žฌ์‚ฌ์šฉ๋˜์ง€๋„ ์•Š๊ณ , ํ•œ ๋ฒˆ์— ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์šฐ์ฃผ์—์„œ ์‚ฌ๋ฌผ์„ ์•”์‹œ ์ ์œผ๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์‚ฌ์‹ค ๋™ํ˜•์ด๋ผ๋Š” ์‚ฌ์‹ค์€ ์ด๊ฒƒ์ด ๋ฌดํ•œํ•œ ์ˆ˜์ค€, ๊ฐ’-> ์œ ํ˜•-> ์ข…๋ฅ˜-> ์ •๋ ฌ-> ...์—์„œ ์‚ฌ๋ฌผ์„ ์ •์˜ ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•˜์ง€๋งŒ, ๋ถˆํ–‰ํ•œ * ๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ๋‹ค๋ฅธ ์‹œ๊ฐ„์— ๋Œ€ํ•œ ์ฃผ์ œ)

์‚ฌ์‹ค,์ด ํŒจํ„ด์€ ๋งค์šฐ ์˜๋ฏธ๊ฐ€์žˆ์–ด ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์€ -> ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•ด ์ผ๋ฐ˜ํ™”ํ•˜๋Š” ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” GHCi ํ™•์žฅ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ™•์žฅ์€ "๋ฐ์ดํ„ฐ ์ข…๋ฅ˜"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋ฉฐ ํ•˜์Šค์ผˆ์ด ์ด๊ธฐ์ข… ๋ชฉ๋ก ( [] ์€ ๊ฐ’ ๋ชฉ๋ก์˜ ์œ ํ˜•๊ณผ ์œ ํ˜• ๋ชฉ๋ก์˜ ์œ ํ˜• ๋ชจ๋‘ ์ž„), ์ด๊ธฐ์ข… ํŠœํ”Œ, "์Šค๋งˆํŠธ ๊ธธ์ด "๋ฒกํ„ฐ ๋ฐ ๊ธฐํƒ€ ๋งŽ์€ ๊ธฐ๋Šฅ.

์•„๋งˆ๋„ ์šฐ๋ฆฌ๋Š” ์•„์ง DataKinds ๊นŒ์ง€ ๊ฐ€๊ณ  ์‹ถ์ง€ ์•Š์„ ๊ฒƒ์ด๋ฏ€๋กœ ์ข…๋ฅ˜ ์ƒ์„ฑ์ž * ๋ฐ -> ๋งŒ ๊ณ ์ˆ˜ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Daniel์ด ์ œ์•ˆํ•œ ๊ตฌ๋ฌธ์„ ๋”ฐ๋ฅด๋ฉด , ๋˜๋Š”๋ณด๋‹ค ์ผ๋ฐ˜์ ์œผ๋กœ ์ข…๋ฅ˜ ์ •์˜๋ฅผ ์œ ํ˜• ์ •์˜์™€ ๋™ํ˜•์œผ๋กœ ๋งŒ๋“ค๋ฉด์ด ์˜์—ญ์˜ ํ–ฅํ›„ ๊ฐœ๋ฐœ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ด์ „ ๋‘์„œ์—†๋Š” ๊ธ€์— ์ด์–ด, ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ถ”์ฒœํ•˜๊ณ  ์‹ถ์€ any ๋Œ€์‹  * ; ์ด๊ฒƒ์€ ๋ชจ๋“  ๊ฐ’์˜ ์œ ํ˜•๊ณผ ๋ชจ๋“  ์œ ํ˜•์˜ ์œ ํ˜•์„ ๋ชจ๋‘ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ตฌ๋ฌธ์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์›Œ ๋ณด์ด๋ฉด Haskell์˜ ์ฑ…์—์„œ ํŽ˜์ด์ง€๋ฅผ ๊บผ๋‚ด ' ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ข…๋ฅ˜์™€ ์œ ํ˜•์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

OP์˜ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

interface Monad<(T: 'any => 'any)> {
    // ...
}

Nitpick : any ์€ (๋Š”) ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ์ ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ํ˜ผ๋ž€ ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.
never๊ฐ€ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์˜ ํ•˜์œ„ ์œ ํ˜• ์ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์˜ ์Šˆํผ ์œ ํ˜•์ด๋ฏ€๋กœ ํ•จ์ˆ˜๊ฐ€ any ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์š”์ฒญํ•˜๋ฉด ๋ฌด์—‡์ด๋“  ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌํƒœ๊นŒ์ง€๋Š” ๊ทธ๋Ÿฐ๋Œ€๋กœ ์ž˜๋๋‹ค.
์žฌ๋ฏธ์žˆ๋Š” ๋ถ€๋ถ„์€ ํ•จ์ˆ˜๊ฐ€ ํŠน์ •ํ•œ ๊ฒƒ์„ ์š”๊ตฌํ•˜๊ณ  any ๋ฅผ ์ œ๊ณต ํ•  ๋•Œ์ž…๋‹ˆ๋‹ค. ์ด ์œ ํ˜• ๊ฒ€์‚ฌ๋Š” ์š”์ฒญ ๋œ ๊ฒƒ๋ณด๋‹ค ๋” ๊ด‘๋ฒ”์œ„ํ•œ ๋‹ค๋ฅธ ์œ ํ˜•์€ ๋Œ€์‹  ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๊ทธ๋ž˜, ๋ญ๋“ .

๋˜ ๋‹ค๋ฅธ ๋ฉ”๋ชจ์—์„œ ' ๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์—์„œ๋„ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜ผ๋ž€ ์Šค๋Ÿฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@Artazor ์ด๊ฒƒ์— ๋Œ€ํ•œ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์ง€๋‚œ๋ฒˆ์— ๊ธฐ๋ณธ ์ผ๋ฐ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๋ฆฌ๋ฒ ์ด์Šคํ•ด์•ผํ•œ๋‹ค๊ณ  ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์‹ ์€ ์ž‘๋™ํ•˜๋Š” POC์— ์ถฉ๋ถ„ํžˆ ๊ฐ€๊นŒ์šด ์œ ์ผํ•œ ์‚ฌ๋žŒ์ด๋ผ๊ณ  ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด๊ฒƒ์ด ํ•˜์œ„ ํƒ€์ดํ•‘๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. * ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ œํ•œ๋œ ๋‹คํ˜•์„ฑ ๋Œ€์‹  ์ž„์‹œ ๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ์–ธ์–ด์—์„œ๋Š” ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์œ ํ˜• ์ธ์ˆ˜๋ฅผ ์ œํ•œํ•˜๊ธฐ์œ„ํ•œ ์ œ์•ฝ ์œ ํ˜•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Monad T ์˜ ์ข…๋ฅ˜๋Š” ์‹ค์ œ๋กœ Constraint ๊ฐ€ ์•„๋‹ˆ๋ผ * ์ž…๋‹ˆ๋‹ค.

TypeScript์—์„œ๋Š” ๊ตฌ์กฐ์  ํ•˜์œ„ ์œ ํ˜•์„ ๋Œ€์‹  ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์œ ํ˜• ๊ฐ„์˜ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ๋ฐ˜์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฃผ์ œ์— ๋Œ€ํ•œ ์Šค์นผ๋ผ ๋…ผ๋ฌธ์€ ์ผ์ข…์˜ ์‹œ์Šคํ…œ์˜ ๋ถ„์‚ฐ ๋ฐ ํ•˜์œ„ ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ข‹์€ ์•„์ด๋””์–ด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค " ๋†’์€ Kinded ์œ ํ˜•์— ๋Œ€ํ•œ ํ‰๋“ฑ๊ถŒ์„ ํ–ฅํ•ด ".

์ด๊ฒƒ์— ๋Œ€ํ•œ ์ง„์ „์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@gcanti https://medium.com/@gcanti/higher -kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe์˜ ๋Œ€์ฒด ์ ‘๊ทผ ๋ฐฉ์‹

fp-ts๊ฐ€ ์ทจํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ๋ฌธ์ œ์ ์€ ์ž…์ฆ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜์—๊ฒŒ typescript์˜ ์•„์ด๋””์–ด๋Š” ํ˜„์žฌ JavaScript์—์„œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋กœ ์ƒ๊ฐ๋˜๋Š” ๊ฒƒ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž…๋ ฅ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด์ง€ ts ๋ฐฉ์‹์œผ๋กœ ๋‹ค์‹œ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์š”ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—๋Š” ํŒํƒ€์ง€ ๋žœ๋“œ, ๋žŒ๋‹ค ๋˜๋Š” ๋ฆฌ ์•กํŠธ ํผ๊ณผ ๊ฐ™์€ js libs์—์„œ ํ˜„์žฌ ์‚ฌ์šฉํ•˜๋Š” ๊ณ„์•ฝ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด HKT๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๋Š” ๋งŽ์€ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ถฉ๋Œ์„ ๋ณด๋Š” ๊ฒƒ์ด ์ •๋ง ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค :)

~์ด ์ผ์„ ํ•  ์˜ํ–ฅ์ด ์žˆ๊ฑฐ๋‚˜ ํ•  ์ˆ˜์žˆ๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋…ผ์˜๋ฅผ ์œ„ํ•ด ์ € ์—๊ฒŒ

@gcanti https://medium.com/@gcanti/higher -kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe์˜ ๋Œ€์ฒด ์ ‘๊ทผ ๋ฐฉ์‹

๋‚˜๋Š” ๊ฒฐ๊ณผ map ์—ฌ์ „ํžˆ Option ์ปจํ…Œ์ด๋„ˆ ์œ ํ˜•์„ ๋ช…์‹œ ์ ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ๋”ฐ๋ผ์„œ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜• (HKT) ๋ฐฉ์‹์œผ๋กœ ์™„์ „ํžˆ ์ œ๋„ค๋ฆญ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—์ด๋ฅผ ์™„์ „ํžˆ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

function map<A, B>(f: (a: A) => B, fa: HKTOption<A>): Option<B> {
  return (fa as Option<A>).map(f)
}

@spion์ด 2016 ๋…„ 8 ์›” 26 ์ผ์— ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด HKT๋Š” ํŒฉํ† ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๊ณ  ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™” ๋œ ์ปจํ…Œ์ด๋„ˆ ์œ ํ˜• ์ž์ฒด๊ฐ€ ์ œ๋„ค๋ฆญ ์ธ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๋””์ž์ธ์— ๋Œ€ํ•œ ํ† ๋ก ์—์„œ

์ถ”์‹  ๊ถ๊ธˆํ•˜๋‹ค๋ฉด์ด ๊ธฐ๋Šฅ ์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ์ € ( @keean ํฌํ•จ) ๋ถ„์„์— ํฌ๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค .

@ shelby3 FWIW Option ์˜ map (in Option.ts )๋Š” ์ธ์Šคํ„ด์Šค ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ Functor ์˜ map (in Functor.ts )๋Š” ํด๋ž˜์Šค ์œ ํ˜•์„ ๋‚˜ํƒ€ ๋‚ด๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ชจ๋“  ํŽ‘ํ„ฐ ์ธ์Šคํ„ด์Šค์™€ ํ•จ๊ป˜ ์ž‘๋™ ํ•  ์ˆ˜์žˆ๋Š” ์ผ๋ฐ˜ lift ํ•จ์ˆ˜๋ฅผ ์ •์˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ถฉ๋Œ์„ ๋ณด๋Š” ๊ฒƒ์ด ์ •๋ง ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค :)

๋‚˜๋Š” ๊ฐ•๋ ฅํžˆ ๋™์˜ํ•œ๋‹ค :)

@ shelby3 : ์ด์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๋ณ‘ํ•ฉํ•˜๋ ค๋ฉด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€
TS ๋กœ๋“œ๋งต์—์„œ ์šฐ์„  ์ˆœ์œ„๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ๋ช‡ ๊ฐ€์ง€ PR์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.
์ž‘์€ ์ˆ˜์ •์ด๋‚˜ ์ด๋ฏธ ์ฐพ๊ณ ์žˆ๋Š” ๊ฒฝ์šฐ ํ”ผ๋“œ๋ฐฑ / ๋ณ‘ํ•ฉ
๊ทธ๋“ค์—. ๋‚˜๋Š” ๋ถ€์ •์ ์ด๊ธฐ ์‹ซ์ง€๋งŒ ๋งŒ์•ฝ ๋‹น์‹ ์ด
์—ฌ๊ธฐ์— ์ž์›์„ ํˆฌ์žํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

2018 ๋…„ 1 ์›” 8 ์ผ ์˜คํ›„ 4:05์— "shelby3" [email protected]์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ผ์„ ํ•  ์˜ํ–ฅ์ด ์žˆ๊ฑฐ๋‚˜ ํ•  ์ˆ˜์žˆ๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋ถ€๋‹ด์—†์ด ๋ฌธ์˜
์ €์—๊ฒŒ [email protected] ์„ ๋…ผ์˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ๋ˆ„๊ตฌ๋“ ์ง€ ์ฝ”์น˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๊ฐ€์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์—๊ฒŒ๋„ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

@gcanti https://github.com/gcanti ์˜ ๋Œ€์ฒด ์ ‘๊ทผ ๋ฐฉ์‹
https://medium.com/@gcanti/higher -kinded-types-in-
ํƒ€์ดํ”„ ์Šคํฌ๋ฆฝํŠธ ์ •์  ๋ฐ ํŒํƒ€์ง€ ๋žœ๋“œ d41c361d0dbe

๊ทธ ๊ฒฐ๊ณผ ๋งต์„ ๊ด€์ฐฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์™„์ „ํžˆ ๊ทธ๋Ÿญ์ €๋Ÿญ ๊ท€์ฐฎ๊ฒŒํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
์—ฌ์ „ํžˆ ๋ช…์‹œ ์ ์œผ๋กœ Option ์ปจํ…Œ์ด๋„ˆ ์œ ํ˜•์„ ์ง€์ •ํ•˜๋ฏ€๋กœ ์™„์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ณ ๊ธ‰ ์œ ํ˜• (HKT)์ด ์ œ๊ณต ํ•  ์ˆ˜์žˆ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹ :

ํ•จ์ˆ˜ ๋งต (f : (a : A) => B, fa : HKTOption ) : Option { return (fa as Option ) .map (f) }

HKT๋Š” ๊ณต์žฅ ๋ฐ
์—ฌ๊ธฐ์„œ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™” ๋œ ์œ ํ˜• ์ปจํ…Œ์ด๋„ˆ ์œ ํ˜•์€ ๊ทธ ์ž์ฒด๋กœ ์ œ๋„ค๋ฆญ์ด๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š”
์ด https://github.com/keean/zenscript/issues/10 ์„ ํƒ์ƒ‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๋””์ž์ธ์— ๋Œ€ํ•œ ํ† ๋ก .

์ถ”์‹  : ๊ถ๊ธˆํ•˜๋‹ค๋ฉด์ด ๊ธฐ๋Šฅ์€ ๋‚ด
( @keean https://github.com/keean 's ํฌํ•จ) ๋ถ„์„
ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ํ™˜๊ฒฝ
https://github.com/keean/zenscript/issues/35#issuecomment-355850515 ๋‚˜๋Š”
์šฐ๋ฆฌ์˜ ๊ฒฌํ•ด๊ฐ€ Typescript์˜ ์šฐ์„  ์ˆœ์œ„์™€ ์™„์ „ํžˆ ๊ด€๋ จ์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์œผ์‹ญ์‹œ์˜ค.
Javascript / ECMAScript ๋ฐ ์ง€์›์˜ ์ƒ์œ„ ์ง‘ํ•ฉ์ด๋˜๋Š” ๊ฒƒ์ด ์ฃผ์š” ๋ชฉํ‘œ์ž…๋‹ˆ๋‹ค.
๊ทธ ์ƒํƒœ๊ณ„.

โ€”
์ด ์Šค๋ ˆ๋“œ๋ฅผ ๊ตฌ๋…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—์ด ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/Microsoft/TypeScript/issues/1213#issuecomment-355990644 ,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AC6uxYOZ0a8G86rUjxvDaO5qIWiq55-Fks5tIi7GgaJpZM4C99VY
.

@gcaniti ๋Š” ์†Œ์Œ์— ๋Œ€ํ•ด ์‚ฌ๊ณผํ•˜๊ณ  ์ถ”๊ฐ€ ์„ค๋ช…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋…ผํ‰ํ•˜๊ธฐ ์ „์— ๋” ๋งŽ์ด ๊ณต๋ถ€ ํ–ˆ์–ด์•ผํ–ˆ๋‹ค. ๋ฌผ๋ก  ํŽ‘ํ„ฐ์—๋Š” ์ธ์Šคํ„ด์Šค ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋…ํ™”์˜ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.

Afaics, ๋‹น์‹ ์˜ ์˜๋ฆฌํ•œ "ํ•ดํ‚น"์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํŒฉํ† ๋ฆฌ๋ฅผ ์ฐธ์กฐ ํ•  ์ˆ˜์žˆ๊ฒŒ ํ•ด์ฃผ์ง€ lift (์˜ˆ : Option . ์ผ๋ฐ˜์ ์ธ ํŒฉํ† ๋ฆฌ์˜ ๋ชจ๋“  ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์ƒ์šฉ๊ตฌ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด ์ผ๋ฐ˜์ ์ธ sort ์˜ˆ์ œ @keean ๊ณผ ์ œ๊ฐ€ ๋…ผ์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ฝ”๋„ˆ ์ผ€์ด์Šค๋„ ๋ฐœ๊ฒฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

Kotlin์ด ์•„์ด๋””์–ด๋ฅผ ๋ณต์‚ฌ ํ–ˆ๋‚˜์š”? ์•„๋‹ˆ๋ฉด ๊ทธ ๋ฐ˜๋Œ€์ธ๊ฐ€์š”? (ํ•ด๋‹น ๋งํฌ์—์„œ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ๋น„ํŒ์ด ์žˆ์ง€๋งŒ Typescript ์‚ฌ๋ก€์— ์ ์šฉ๋˜๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค)

๋‚˜๋Š” ๋ถ€์ •์ ์ด๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š์ง€๋งŒ ์ž์›์„ ์ด๊ฒƒ์— ํˆฌ์žํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๊ณ ๋ คํ•  ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜ ๊ทธ ์ƒ๊ฐ๋„ ๋‚˜์—๊ฒŒ ์ƒ๊ฒผ๋‹ค. ์„ค๋ช… ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๋ ค ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜๋Š” @masaeedu๊ฐ€ ์ง€์ ํ•œ ๋ฐ”์™€ ๊ฐ™์ด ์œ ํ˜• ์‹œ์Šคํ…œ๊ณผ ์ƒ์„ฑ ํ•  ์ˆ˜์žˆ๋Š” ๋ชจ๋“  ์ฝ”๋„ˆ ์ผ€์ด์Šค์— ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฏธ์น˜๋Š” ์˜ํ–ฅ ์ผ

์ฐธ๊ณ  EMCAScript ์ปดํŒŒ์ผ ๋Œ€์ƒ์— ๋Œ€ํ•œ ํˆฌ์ž ์ˆ˜์ค€์„ ๋” ์ž˜ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด Ceylon๋„ ์กฐ์‚ฌ โ€‹โ€‹์ค‘์ž…๋‹ˆ๋‹ค. (๋” ๊ณต๋ถ€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค).

๋‚˜๋Š” ๋˜ํ•œ์ด ํ•œ๊ณ„์— ๋ฌผ๋ ธ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ์—์„œ I ๋ฅผ ์ž๋™์œผ๋กœ ์ถ”๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

interface IdType<T> {
  id: T;
}

interface User {
  id: number;
  name: string;
}

function doStuff<T extends IdType<I>>() {
  const recs = new Map<I, T>();
  return {
    upsert(rec: T) {
      recs.set(rec.id, rec);
    },
    find(id: I) {
      return recs.get(id);
    },
  };
}

(function () {
  const stuff = doStuff<User>();
  stuff.upsert({id: 2, name: "greg"});
  console.log(stuff.find(2));
})();

๋‚ด๊ฐ€ ์•Œ ์ˆ˜์žˆ๋Š” ํ•œ, ์ด๊ฒƒ์€ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ์ค‘๋ณต๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ์ค‘๋ณต ์ผ๋ฐ˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ (์˜ˆ : doStuff<User, number>() )๋ฅผ ์ง€์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ตœ๊ทผ์—์ด ํ•œ๊ณ„์— ๋ถ€๋”ชํ˜”๋‹ค.

๋‚˜๋Š” ์•ฝ์† ์„์œ„ํ•œ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์€ ์•ˆ์— ๋„ฃ์€ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์œ ํ˜•์˜ promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Bluebird promise๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•จ์ˆ˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ์ถ”๊ฐ€ ๊ธฐ๋Šฅ๊ณผ ํ•จ๊ป˜ Bluebird promise๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ํƒ€์ž… ์‹œ์Šคํ…œ์ด ์ธ์ฝ”๋”ฉ ์‹ถ์—ˆ์ง€๋งŒ, ๋‚˜๋Š” ๋นจ๋ฆฌ ์œ ํ˜• ์ž‘์—…์ด ํ•„์š”ํ•œ ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๋‹ค P ์ข…๋ฅ˜์˜ * -> * ๋“ฑ์ด P<T> extends Promise<T> .

๋‹ค์Œ์€ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

/**
* Returns a promise that waits for `this` to finish for an amount of time depending on the type of `deadline`.
* If `this` does not finish on time, `onTimeout` will be called. The returned promise will then behave like the promise returned by `onTimeout`.
* If `onTimeout` is not provided, the returned promise will reject with an Error.
*
* Note that any code already waiting on `this` to finish will still be waiting. The timeout only affects the returned promise.
* <strong i="14">@param</strong> deadline If a number, the time to wait in milliseconds. If a date, the date to wait for.
* <strong i="15">@param</strong> {() => Promise<*>} onTimeout Called to produce an alternative promise once `this` expires. Can be an async function.
*/
timeout(deadline : number | Date, onTimeout ?: () => PromiseLike<T>) : this;

์œ„์˜ ์ƒํ™ฉ์—์„œ ๋‚˜๋Š” ๋‹ค์†Œ ํ•ดํ‚ค ํ•œ this ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ํ•„์š”๋ฅผ ํ”ผํ•  ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

/**
* Returns a promise that will await `this` and all the promises in `others` to resolve and yield their results in an array.
* If a promise rejects, the returned promise will rejection with the reason of the first rejection.
* <strong i="21">@param</strong> {Promise<*>} others The other promises that must be resolved with this one.
* <strong i="22">@returns</strong> {Promise<*[]>} The return type is meant to be `Self<T[]>`, where `Self` is the promise type.
*/
and(...others : PromiseLike<T>[]) : ExtendedPromise<T[]>;

this<T[]> ๊ฒƒ์„ ํ•  ์ˆ˜์žˆ๋Š” ํ•ดํ‚น์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ฌธ์„œ์—์„œ ๋‚ด ์ž‘์€ ์‚ฌ๊ณผ๋ฅผ ๊ธฐ๋กํ•˜์‹ญ์‹œ์˜ค.

์œ„์˜ ์ฐธ์กฐ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด์ด ๊ธฐ๋Šฅ์ด ์œ ์šฉ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (์ œ์•ˆ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด์„ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •).

์ œ๋„ค๋ฆญ ์œ ํ˜•์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ํ•ด๋‹น ํŒจํ‚ค์ง€์—์„œ ์œ ํ˜•์ด ์ง€์ •๋˜์ง€ ์•Š์€ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค ๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ์œ ํ˜•์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์‹œ๋‚˜๋ฆฌ์˜ค์— ์ œ์•ˆ์„ ์ ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

import { Component, FunctionalComponent } from 'preact';

interface IAsyncRouteProps {
    component?: Component<~,~> | FunctionalComponent<~>;
    getComponent?: (
        this: AsyncRoute,
        url: string,
        callback: (component: Component<~,~> | FunctionalComponent<~>) => void,
        props: any
    ) => Promise<any> | void;
    loading?: () => JSX.Element;
}

export default class AsyncRoute extends Component<IAsyncRouteProps, {}> {
    public render(): JSX.Element | null;
}

๋‚ด ๊ตฌํ˜„์—์„œ ์ œ๋„ค๋ฆญ ์œ ํ˜•์„ ์•ˆ์ •์ ์œผ๋กœ ์ฐธ์กฐ ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ๋ญ”๊ฐ€ ๋†“์นœ ๊ฒƒ์ด ํ™•์‹คํ•ฉ๋‹ˆ๋‹ค.

@ Silic0nS0ldier ์‚ฌ์‹ค ๊ทธ ์‚ฌ๊ฑด์€ ์ง€๊ธˆ ๋‹น์žฅ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ ์ƒ์„ฑ์ž ์œ ํ˜•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

type ComponentConstructor = {
    new<A, B>() : Component<A, B>;
}

๊ทธ๋Ÿฐ ๋‹ค์Œ component ?: ComponentConstructor ๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

๋” ์ผ๋ฐ˜์ ์œผ๋กœ, ์‹ค์ œ๋กœ ์ผ๋ฐ˜ ํ•จ์ˆ˜ ์œ ํ˜•์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let f : <T>(x : T) => T

์ด๋ฅผ rank-n ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋‹คํ˜•์„ฑ์ด๋ผ๊ณ ํ•˜๋ฉฐ ์‹ค์ œ๋กœ ์–ธ์–ด์—์„œ ๋งค์šฐ ๋“œ๋ฌธ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ TypeScript์— ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•์ด์—†๋Š” ์ด์œ ๋Š” ํ›จ์”ฌ ๋” ํ˜ผ๋ž€ ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ›จ์”ฌ ๋” ์ผ๋ฐ˜์ ์ธ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•˜๋Š” ์ œํ•œ์€ ํŠน์ • TComponent<T, S> ๋ฅผ ์ฐธ์กฐํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ท€ํ•˜์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.


typeof Component ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ์ž์˜ ์œ ํ˜• ์ธ Component ์žˆ์ง€๋งŒ ์ด๋กœ ์ธํ•ด ํ•˜์œ„ ์œ ํ˜•์— ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

@GregRos ์ œ์•ˆ ๋œ ์†”๋ฃจ์…˜์ด ์œ ๋ง ํ•ด ๋ณด์˜€์ง€๋งŒ (์ •์˜ ํŒŒ์ผ ๋‚ด์˜ ์œ ํ˜•์„ ํ—ˆ์šฉ ํ•จ) ํ˜ธํ™˜ ๊ฐ€๋Šฅํ•œ ์œ ํ˜•์ด ๊ฑฐ๋ถ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. https://gist.github.com/Silic0nS0ldier/3c379367b5e6b1abd76e4a41d1be8217

@ Silic0nS0ldier ์š”์ ์— ๋Œ€ํ•œ ๋‚ด ์˜๊ฒฌ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

@chrisdavies ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ?

interface IdType<T> {
    id: T;
}

interface User {
    id: number;
    name: string;
}

function doStuff<T extends IdType<any>>() {
    type I = T['id']; // <==== Infer I
    const recs = new Map<I, T>();
    return {
        upsert(rec: T) {
            recs.set(rec.id, rec);
        },
        find(id: I) {
            return recs.get(id);
        },
    };
}

(function() {
    const stuff = doStuff<User>();
    stuff.upsert({ id: 2, name: "greg" });
    console.log(stuff.find(2));
})();

@ jack-williams ๋„ค. ๊ทธ๊ฒƒ์€ ๋‚ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ฌธ์„œ์—์„œ ๊ทธ ์˜ˆ์ œ๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค (๋‚˜๋Š” ๋ˆ„๋ฝ ๋œ ๊ฒƒ์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์ง€๋งŒ!). ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๋‚˜๋Š”์ด ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๋งŽ์ด ์ƒ๊ฐํ•˜๊ณ  ์žˆ๊ณ , ์–ด๋–ค ์ข…๋ฅ˜์˜ ์‚ฌ์–‘์— ๊ธฐ๋Œ€์–ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ์•ฝ๊ฐ„์˜ ์ƒ๊ฐ์ด ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ œ์•ˆ์€ ์ง€๊ธˆ๊นŒ์ง€ ์ œ์•ˆ ๋œ ๊ฒƒ๊ณผ ์•ฝ๊ฐ„ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.


์šฐ์„ , ์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•ด T<*, *> ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์œ ํ˜• ์ƒ์„ฑ์ž์˜ ๋ณต์žก์„ฑ์— ๋งž๊ฒŒ ํ™•์žฅ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜์œ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฐธ์กฐ ๋  ๋•Œ๋งˆ๋‹ค ์œ ํ˜• ์ƒ์„ฑ์ž์˜ ์ข…๋ฅ˜๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€์žˆ๋Š” ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋„ ํ•จ์ˆ˜์— ๋Œ€ํ•ด์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

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

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฅธ ์œ ํ˜•๊ณผ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค ์ข…๋ฅ˜์˜ ์ ‘๋‘์‚ฌ ๋˜๋Š” ์ ‘๋ฏธ์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ผ๋ฐ˜ ์ฝ”๋“œ ๋งŒ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์œ ํ˜• ์ƒ์„ฑ์ž์™€ ๊ด€๋ จ๋œ ์ดํ•ดํ•  ์ˆ˜์—†๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋กœ๋ถ€ํ„ฐ ์‚ฌ์šฉ์ž๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค. ์ €๋Š” ~Type, ^Type, &Type ๊ฐ™์€ ๋ชจ์Šต์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ํ•จ์ˆ˜ ์„œ๋ช…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

interface List<T> {
    push(x : T);
}

function mapList<~L extends ~List, A, B>(list : L<A>, f : (x : A) => B) : L<B>;

(๊ณ ์˜์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์œ ํ˜•์— ~ ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค)

์—ฌ๊ธฐ์„œ extends ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‘ ๊ฐ€์ง€๋ฅผ ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.

**1. ํ•„์š”ํ•œ ๊ฒฝ์šฐ : ~L ๋Š” ~List ์™€ ๋™์ผํ•œ ์ข…๋ฅ˜๋ฅผ ๊ฐ–๋Š” ์œ ํ˜• ์ƒ์„ฑ์ž์ž…๋‹ˆ๋‹ค. ์ฆ‰, * -> * ์ข…๋ฅ˜ (๋˜๋Š” => ์ดํ›„ * => * ) => ๋Š” TypeScript ํ™”์‚ดํ‘œ์ž…๋‹ˆ๋‹ค).

  1. ~L ์€ ~List ์˜ ํ•˜์œ„ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. **

์œ ํ˜• ์ƒ์„ฑ์ž์˜ ์ข…๋ฅ˜๋ฅผ ๋‚˜ํƒ€ ๋‚ด๊ธฐ ์œ„ํ•ด extends ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ((* => *) => (* => *)) => * ์™€ ๊ฐ™์€ ๊ฒƒ์„ ํฌํ•จํ•˜์—ฌ ์ž„์˜์˜ ๋ณต์žกํ•œ ์œ ํ˜• ์ƒ์„ฑ์ž๋กœ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.

์œ ํ˜•์˜ ์‹๋ณ„์ž์—์„œ ๊ทธ๋Ÿฐ ์ข…๋ฅ˜๋ฅผ ์‹ค์ œ๋กœ ๋ณผ ์ˆ˜๋Š” ์—†์ง€๋งŒ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ ํ˜• ์ƒ์„ฑ์ž ๊ฐ„์˜ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๊ฐ€ ์ข…๋ฅ˜๋ฅผ ๋ณด์กดํ•ด์•ผํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ (1)์ด ํ•„์š”ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถˆ์™„์ „ํ•œ ์œ ํ˜• ์ƒ์„ฑ ์—†์Œ

๋ถˆ์™„์ „ํ•œ ์œ ํ˜• ์ƒ์„ฑ์„ ์ง€์›ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

(*, *) => * => *

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๊ฐ€์น˜๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  ์œ ํ˜• ์ƒ์„ฑ์ž๋Š” ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์„ ์ƒ์„ฑํ•ด์•ผํ•˜๋ฉฐ ํ•ด๋‹น ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์€ TC๊ฐ€ ์ •์˜ ๋œ ์ปจํ…์ŠคํŠธ์—์„œ ์ง€์ •๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•˜๋Š” ๊ตฌ์กฐ์  ๋ฐฉ๋ฒ•

๋˜ํ•œ ๋งค์šฐ ๋†’์€ ์ˆœ์„œ์˜ ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ ์œ ํ˜•์„ ํฌํ•จํ•˜์—ฌ ๋‹ค๋ฅธ ์œ ํ˜•์„ ๊ตฌ์กฐ์ ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ตฌ์กฐ์  ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ๋ฌธ์„ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

~<A, B> { 
    a : A,
    b : B
}

์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€์žˆ๋Š” ํ•จ์ˆ˜ ์œ ํ˜•์˜ ๊ธฐ์กด ๊ตฌ๋ฌธ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

<A, B>() => { a : A, b : B};

์ด ๋‘ ๊ฐ€์ง€๋ฅผ ๊ฒฐํ•ฉํ•˜์—ฌ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

~<A><B, C> => [A, B, C]

์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•˜๋Š” ์œ ํ˜• ์ƒ์„ฑ์ž์ž…๋‹ˆ๋‹ค.

์ด์ ์€ ๋‹ค๋ฅธ ๊ตฌ์กฐ ์œ ํ˜•์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ์œ ํ˜• ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์ •ํ•  ๋•Œ ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ ์œ ํ˜•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ์ด๊ฒƒ์€ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐ ํ•  ์ˆ˜์—†๋Š” ์ฐธ์กฐ ์ง€์—ญ ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๊ทธ ์˜ˆ์ž…๋‹ˆ๋‹ค.

type List<A, B> = ...;

type AdvancedType<~L extends ~<A>List<A, B>, B> = ...;

์œ„์˜ ์˜ˆ์—์„œ ๊ตฌ์กฐ์  ์œ ํ˜• ์ƒ์„ฑ์ž ~<A>List<A, B> ๋Š” ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ B ํ•ฉ๋‹ˆ๋‹ค. ์ ์–ด๋„ ๋ถ€๋ถ„์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์œ ํ˜• List<A, *> ๋ฅผ ์ธ์ฝ”๋”ฉํ•˜์ง€ ์•Š๊ณ ๋Š”์ด ๊ด€๊ณ„๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์˜ˆ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„

ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋Š” ์˜๋ฏธ๊ฐ€์žˆ๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ํŠน์„ฑํ™”ํ•˜๋Š” ๋ฐ ๋งŽ์€ ์–ด๋ ค์›€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ฒซ ๋ฒˆ์งธ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~A ๊ฐ€ ~B ์˜ ํ•˜์œ„ ์œ ํ˜•์ด๋˜๋Š” ๊ฒฝ์šฐ :

  1. (a) ๊ทธ๊ฒƒ๋“ค์€ ๋™์ผํ•œ ์ข…๋ฅ˜๋ฅผ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค (์ œ์•ฝ์ด ์•„๋‹ˆ๋ผ arity ์ธก๋ฉด์—์„œ).
  2. ๋ชจ๋“  ๋ฒ•์  ํŒŒ๋ผ๋ฏธํ„ฐ (๋‚˜) Tโ‚, Tโ‚‚, ... ์˜ ~A , A<Tโ‚, Tโ‚‚, ...> ์˜ ํ•˜์œ„ ์œ ํ˜•์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค B<Tโ‚, Tโ‚‚, ...> .

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. MySpecialPromise ํด๋ž˜์Šค ๋Š” PromiseLike {}๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  2. MyArrayPromise ํด๋ž˜์ŠคPromiseLike ๊ตฌํ˜„

    ์ด ๊ฒฝ์šฐ์—๋„ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๊ฐ€ ๋ณด์กด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

(b)์˜๋ณด๋‹ค ์ผ๋ฐ˜ํ™” ๋œ ๋ฒ„์ „์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ํ•ฉ๋ฒ•์  ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ (๋‚˜) Tโ‚, Tโ‚‚, ... ์˜ ~A , ํŒŒ๋ผ๋ฏธํ„ฐ ํ™” ์กด์žฌ Sโ‚, Sโ‚‚, ... ์˜๋ฅผ ~B ๋˜๋„๋ก A<Tโ‚, Tโ‚‚, ...> ์˜ ํ•˜์œ„ ์œ ํ˜• B<Sโ‚, Sโ‚‚, ...>

์ฆ‰, ์œ„์˜ ์†์„ฑ์„ ๊ฐ€์ง„ ๋งคํ•‘ F (Tโ‚, Tโ‚‚, ...) = Sโ‚, Sโ‚‚, ...๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋งตํ•‘์€ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค B<...> A๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ A<...> . ์œ ํ˜• ์ƒ์„ฑ์ž๊ฐ€ ๋‹ค๋ฅธ ์ข…๋ฅ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„์ด๋ฅผ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ด€๊ณ„์˜ ๋ฌธ์ œ๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋งคํ•‘์„ ์ฐพ์„ ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ช…๋ชฉ์ƒ ํƒ€์ดํ•‘์„ ์‚ฌ์šฉํ•˜๋Š” ์–ธ์–ด์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชจ๋“  ๋ฌธ์žฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

A<...> extends B<...>

~A ์˜ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ~B ์˜ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ ๊ฐ„์˜ ๋งตํ•‘์„ ์ •์˜ํ•˜๋ฏ€๋กœ ๋งตํ•‘์ด ๋ณต๊ตฌ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ TypeScript์˜ ๊ตฌ์กฐ์  ์œ ํ˜• ์ฒด๊ณ„์—์„œ๋Š”์ด ์œ ํ˜•์˜ ๋ช…์‹œ ์  ์ง„์ˆ ์— ์˜์กด ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ implements ์ ˆ์ด๋‚˜ Scala์™€ ์œ ์‚ฌํ•œ ์ผ์ข…์˜ ์ถ”์ƒ ์œ ํ˜• ๋ฉค๋ฒ„์™€ ๊ฐ™์€ ์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜• ์ •๋ณด๋ฅผ ๊ฐ€์ง„ ์œ ํ˜•์— ๋Œ€ํ•ด์„œ๋งŒ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ด๊ฒƒ์ด ์•ž์œผ๋กœ ๋‚˜์•„๊ฐˆ ๊ธธ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@GregRos- ํฅ๋ฏธ๋กœ์šด ๋ฉ”๋ชจ! ๋ช‡ ๊ฐ€์ง€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค.


๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์ด๋ž€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? * ์ข…๋ฅ˜๋ฅผ ๊ฐ€์ง„ ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋ฐ”์ธ๋”ฉ ๋œ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€์—†๋Š” ์œ ํ˜•์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?


๋ถˆ์™„์ „ํ•œ ์œ ํ˜• ์ƒ์„ฑ ์—†์Œ
๋ถˆ์™„์ „ํ•œ ์œ ํ˜• ์ƒ์„ฑ์„ ์ง€์›ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
(*, *) => * => *

๋ถˆ์™„์ „ํ•œ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? L<A> ์™€ ๊ฐ™์€ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด * ? ์˜ˆ๋ฅผ ๋“ค์–ด ์Œ ์ข…๋ฅ˜ ์ƒ์„ฑ์ž๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด (* => *) => * => * ๊ดœ์ฐฎ์Šต๋‹ˆ๊นŒ?


์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•˜๋Š” ๊ตฌ์กฐ์  ๋ฐฉ๋ฒ•

~<A, B> { 
    a : A,
    b : B
}
inferface TyCon<A, B> { 
    a : A,
    b : B
}

์ฒซ ๋ฒˆ์งธ ์˜ˆ๊ฐ€ ์ต๋ช… ์ธ ๊ฒƒ ์™ธ์— ๋‹ค๋ฅธ ์˜ˆ์ž…๋‹ˆ๊นŒ?


ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„

~A ๋ฐ ~B ๋Š” ์œ ํ˜•์„ ์ฐธ์กฐํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ? ํ•œ ์ƒ์„ฑ์ž๊ฐ€ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž์˜ 'ํ•˜์œ„ ์œ ํ˜•'์ธ์ง€ ์‹ค์ œ๋กœ ์–ธ์ œ ํ™•์ธํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ? ์ƒ์„ฑ์ž๊ฐ€ ์ ์šฉ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๊ฒฐ๊ณผ ์œ ํ˜•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@ jack-williams ํ”ผ๋“œ๋ฐฑ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

๋ถˆ์™„์ „ํ•œ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? L<A> ์™€ ๊ฐ™์€ ๋ชจ๋“  ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— ์ข…๋ฅ˜ *๊ฐ€ ์žˆ์–ด์•ผํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด ์Œ ์ข…๋ฅ˜ ์ƒ์„ฑ์ž๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด (* => *) => * => * ๊ดœ์ฐฎ์Šต๋‹ˆ๊นŒ?

๋„ค, ๋งž์Šต๋‹ˆ๋‹ค. L<A> ์™€ ๊ฐ™์€ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—๋Š” * ์ข…๋ฅ˜๊ฐ€ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์–ด๋–ป๊ฒŒ ํŒ”๋ ธ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.


์ฒซ ๋ฒˆ์งธ ์˜ˆ๊ฐ€ ์ต๋ช… ์ธ ๊ฒƒ ์™ธ์— ๋‹ค๋ฅธ ์˜ˆ์ž…๋‹ˆ๊นŒ?

์ฒซ ๋ฒˆ์งธ๋Š” ์œ ํ˜• ํ‘œํ˜„์‹์ด๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ์„ ์–ธ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์œ ํ˜•์ด ๋Œ€๋ถ€๋ถ„์˜ ์ธก๋ฉด์—์„œ ๋™์ผํ•˜๋‹ค๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์ธก๋ฉด์—์„œ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

{
     a : number;
     b : string;
}

interface Blah {
    a : number;
    b : string;
}

๊ตฌ๋ฌธ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋™๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. TypeScript์˜ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ˜•์‹ ์ƒ์„ฑ์ž๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ์ต๋ช…์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ํ•จ์ˆ˜์˜ ํ˜•์‹ ์„œ๋ช…๊ณผ ๊ฐ™์ด ์„ ์–ธ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜์—†๋Š” ํŠน์ • ์ปจํ…์ŠคํŠธ์—์„œ ํ˜•์‹ ์‹ (์œ„์— ์–ธ๊ธ‰ ๋œ ์ต๋ช… ๊ฐœ์ฒด ํ˜•์‹)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋กœ์ปฌ ์‹๋ณ„์ž๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  ๋‹ฌ๋ฆฌ ํ‘œํ˜„ํ•  ์ˆ˜์—†๋Š” ๊ฒƒ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

~A ๋ฐ ~B ๋Š” ์œ ํ˜•์„ ์ฐธ์กฐํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ? ํ•œ ์ƒ์„ฑ์ž๊ฐ€ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž์˜ 'ํ•˜์œ„ ์œ ํ˜•'์ธ์ง€ ์‹ค์ œ๋กœ ์–ธ์ œ ํ™•์ธํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ? ์ƒ์„ฑ์ž๊ฐ€ ์ ์šฉ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ๊ฒฐ๊ณผ ์œ ํ˜•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์œ ํ˜• ์ƒ์„ฑ์ž๋Š” ์œ ํ˜•์œผ๋กœ ๊ฐ„์ฃผ๋˜๊ฑฐ๋‚˜ ๊ฐ„์ฃผ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ๋“ค์„ ๊ฐ’์ด์—†๊ณ  ๊ฐ’์˜ ์œ ํ˜•์„ ์š”๊ตฌํ•˜๋Š” ์–ด๋–ค ๋งฅ๋ฝ์—์„œ๋„ ๋‚˜ํƒ€๋‚  ์ˆ˜์—†๋Š” ๋ถˆ์™„์ „ํ•œ ์œ ํ˜•์œผ๋กœ ๊ฐ„์ฃผ ํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ด ๋ฌธ์„œ์—์„œ Scala๊ฐ€ ์ทจํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ฒ ํ•™์ž…๋‹ˆ๋‹ค.

ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„ ๋ž€ ๋ณธ์งˆ์ ์œผ๋กœ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ œํ•œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ์ผ์ข…์˜ "์ ํ•ฉ์„ฑ"๊ด€๊ณ„๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Promise<T> , Bluebird<T> ๋“ฑ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ชจ๋“  ์ข…๋ฅ˜์˜ promise์—์„œ ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ ค๋ฉด TC ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ œํ•œ ํ•  ์ˆ˜์žˆ๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค PromiseLike<T> .

์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ๊ด€๊ณ„์— ๋Œ€ํ•œ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋‹จ์–ด๋Š” ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์œ ํ˜• ์ƒ์„ฑ์ž ๊ฐ„์˜ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function mapPromise<~P extends ~PromiseLike, A, B>(promise : P<A>, func : (x : A) => B) : P<B>;

๊ทธ๋ฆฌ๊ณ  ์ œ์•ฝ ์กฐ๊ฑด ~P extends ~PromiseLike ์€ ์ด๊ฒƒ์ด promise์— ๋Œ€ํ•ด ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜์ด๋ฉฐ promise์—๋งŒ ์ž‘๋™ ํ•จ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ œ์•ฝ ์กฐ๊ฑด์€ ๋˜ํ•œ ํ•จ์ˆ˜ ๋ณธ๋ฌธ ๋‚ด์—์„œ promise ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๋ ค์ง„ PromiseLike<A> ๋“ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ์— ํƒ€์ดํ”„์— ์˜ํ•ด ์ธ์‹๋˜๋Š” ํšŒ์›์€ ์ •ํ™•ํ•˜๊ฒŒ ์ œ์•ฝ์„ ํ†ตํ•ด ์กด์žฌ ์ž…์ฆ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ๋“ค์ด๋‹ค.

๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ Promise<T> extends PromiseLike<T> , ๊ตฌ์กฐ์ ์œผ๋กœ ํ˜ธํ™˜๋˜๊ณ  ์„œ๋กœ ๋Œ€์ฒด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ~Promise extends ~PromiseLike ๊ตฌ์กฐ์ ์œผ๋กœ ํ˜ธํ™˜ ๊ฐ€๋Šฅํ•œ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•˜๋ฏ€๋กœ ์„œ๋กœ ๋Œ€์ฒด ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.


ํ•˜์œ„ ์œ ํ˜• ๋ฌธ์ œ๋กœ ๋ฌธ์ œ๋ฅผ ๊ฐ•์กฐํ•˜๋ ค๋ฉด ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

interface MyPromise<T> extends Promise<T[]> {}

~Promise ์ถ”์ƒํ™”ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ~MyPromise ๋ฅผ ์ถ”์ƒํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋“ค ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์–ด๋–ป๊ฒŒ ํฌ์ฐฉํ•ฉ๋‹ˆ๊นŒ?

์•ž์„œ ์ด์•ผ๊ธฐ ๋งคํ•‘์€์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์ •ํ•ด, ๊ทธ ๋งคํ•‘์ž…๋‹ˆ๋‹ค ~MyPromise ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค, ~Promise ์œผ๋กœ ๊ตฌ์„ฑ ์œ ํ˜• ๋„ˆ๋ฌด์„ ~MyPromise ์˜ ์„œ๋ธŒ ํƒ€์ž…์ด๋‹ค ํ•˜๋‚˜๋Š” ~Promise ์˜ํ•ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ๋งคํ•‘์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

T => T[]

๋ฟก๋ฟก

์ด ๊ฒฝ์šฐ ~MySpecialPromise ๋Š” ์ข…๋ฅ˜๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ~PromiseLike ์˜ ํ•˜์œ„ ์œ ํ˜•์ด ์•„๋‹™๋‹ˆ๋‹ค.

Haskell์—์„œ ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๋Š” ์œ ํ˜•์˜ ๋ถ€๋ถ„์  ์ ์šฉ์„ ํ—ˆ์šฉํ•˜๊ณ  ์œ ํ˜•์„ ์ •์˜ํ•˜์—ฌ ์ตœ์ข… ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ๊ตฌํ˜„์ค‘์ธ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ์ผ์น˜ํ•˜๋„๋กํ•จ์œผ๋กœ์จ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ์˜ˆ์—์„œ MySpecialPromise ๋Š” MySpecialPromise<TSpecial, TPromiseVal> ๋กœ ์ •์˜๋˜๊ณ  ~MySpecialPromise<SpecialType> ๋Š” ~Promise ๋™์ผํ•œ ์ข…๋ฅ˜๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

๋ฟก๋ฟก

ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„ ๋ž€ ๋ณธ์งˆ์ ์œผ๋กœ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ œํ•œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ์ผ์ข…์˜ "์ ํ•ฉ์„ฑ"๊ด€๊ณ„๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Promise์™€ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์•ฝ์†์— ๋Œ€ํ•ด ์ž‘๋™ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ ค๋ฉด, ๋ธ”๋ฃจ ๋ฒ„๋“œ๋“ฑ, PromiseLike ์ธํ„ฐํŽ˜์ด์Šค๋กœ TC ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.์–ด๋–ค ์‹ ์œผ๋กœ๋“ .
function mapPromise<~P extends ~PromiseLike, A, B>(promise : P<A>, func : (x : A) => B) : P<B> ;

๋‚˜๋Š” ๊ทธ ํ•จ์ˆ˜๋ฅผ ์œ ํ˜• ๊ฒ€์‚ฌ ํ•  ๋•Œ ์„ ํƒํ•œ T ๋Œ€ํ•ด BlueBird<T> ๋ฐ PromiseLike<T> ๋ฅผ ํ†ตํ•ฉํ•˜๋ ค๊ณ  ์‹œ๋„ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์ผ ๋ฟ์ด๋ฉฐ ํ•˜์œ„ ์œ ํ˜•์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ์ž ~BlueBird ๋ฐ ~PromiseLike ๋Œ€ํ•ด ํŠน๋ณ„ํ•œ ๊ด€๊ณ„๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉ๋  ๊ฒƒ ๊ฐ™์•„์š”?

let x: <P extends ~PromiseLike>(input : P<A>, func : (x : A) => B) : P<B>;
let y: <P extends ~BlueBird>(input : P<A>, func : (x : A) => B) : P<B>;
x = y;

์—ฌ๊ธฐ์—์„œ y์˜ ์ œ์•ฝ์ด x์˜ ์ œ์•ฝ์„ ์˜๋ฏธํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์ง€๋งŒ TypeScript์—๋Š” BlueBird<T> ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” PromiseLike<T> ๋ฅผ ํ™•์žฅํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ธฐ๊ณ„๊ฐ€ ์•„์ง ์—†์Šต๋‹ˆ๊นŒ?

@ jack-williams ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

~ P๋Š” ๋ชจ๋“  A ์— ๋Œ€ํ•ด P<A> ๊ฐ€ PromiseLike<A> ์˜ ํ•˜์œ„ ์œ ํ˜•์ด๋˜๋Š” ์œ ํ˜• ์ƒ์„ฑ์ž์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ์ข…๋ฅ˜์˜ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์–ด๋–ค ๊ฐœ๋…์„ ์‚ฌ์šฉ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function mapPromise<~P, A, B where P<A> extends PromiseLike<A>>

๊ทธ๋Ÿฌ๋‚˜์ด ๊ตฌ๋ฌธ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์ด ํด๋ž˜์Šค๋ฅผ ์ œํ•œํ•˜๊ธฐ ์œ„ํ•ด ์„ ์–ธ ๋œ ์ง€์ ์—์„œ P<A> ์œ ํ˜•์„ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—์ด ํด๋ž˜์Šค๋ฅผ ์ „ํ˜€ ํ‘œํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

class PromiseCreator<~P extends ~PromiseLike> {
    create<A>() : P<A>;
}

ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹ค์กด ์  ์œ ํ˜• ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

//Here A is not a captured type parameter
//It's an existential type we introduce to constrain ~P
class PromiseCreator<~P with some A where P<A> extends PromiseLike<A>> {
    create<A>() : P<A>;
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ์„ ํƒ์ ์œผ๋กœ ์กด์žฌ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•จ์ˆ˜ ๋˜๋Š” ์œ ํ˜•์˜ ์„œ๋ช… ๋‚ด์—์„œ ์ƒ์„ฑ ๋œ ์œ ํ˜•์„ ํ†ตํ•ด ๋ชจ๋“  ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ œํ•œํ•˜๋„๋ก ์š”๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์กด ์  ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งคํ•‘์ด์žˆ๋Š” ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„์™€ ๋™์ผํ•œ ํ‘œํ˜„๋ ฅ์„ ๊ฐ–๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ((* => *) => *) => * ์™€ ๊ฐ™์€ ์ข…๋ฅ˜๋กœ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ง€์ •ํ•˜๋ ค๋ฉด ๋งŽ์€ ์กด์žฌ ์œ ํ˜•์„ ๋„์ž…ํ•ด์•ผํ•˜๋ฉฐ, ๊ทธ์ค‘ ์ผ๋ถ€๋Š” ๋” ๋†’์€ ์ˆœ์„œ ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค ๋ชจ๋‘๋Š” ํ•จ์ˆ˜ ๋˜๋Š” ํด๋ž˜์Šค์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— sppearํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
  2. ๋งคํ•‘์„ ์ฐพ๋Š” ๊ฒƒ๋ณด๋‹ค ๋ฌธ์ œ์˜ ์‹ค์กด ์  ์œ ํ˜•์„ ์ฐพ๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ๊ฒƒ์ด๋ผ๊ณ  ํ™•์‹ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ณด๋‹ค ๋œ ์šฐ์•„ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
  4. ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋‹ค๋ฅธ ์œ ํ˜•์˜ ์œ ํ˜•์„ ์ž ์žฌ์ ์œผ๋กœ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค.

๋ฟก๋ฟก

์–ด๋–ค ์ข…๋ฅ˜์˜ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์–ด๋–ค ๊ฐœ๋…์„ ์‚ฌ์šฉ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

_ ๊ฐœ์ธ์ ์œผ๋กœ _ ํŠน๋ณ„ํ•œ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

function mapPromise<P extends PromiseLike, A, B>(p: P<A>, f: (x: A) => B): P<B>

class PromiseCreator<P extends PromiseLike> {
    create<A>() : P<A>;
}

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ number ์™€ ๊ฐ™์€ ๊ฒƒ์„ null-ary ์ƒ์„ฑ์ž๋กœ ๋ณด๋Š” ๋‚ด ์˜๊ฒฌ ์ผ๋ฟ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ตฌ๋ณ„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ํ•˜์œ„ ์œ ํ˜•์— ๋Œ€ํ•œ ๋‚˜์˜ ๊ฒฌํ•ด๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ๋™์ผํ•œ ๋ฐฐ์—ด์„ ๊ฐ€์ ธ์•ผํ•˜๋ฉฐ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ์Šค์นผ๋ผ ๋…ผ๋ฌธ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•œ ๋ฐ˜ ๋ณ€์„ฑ ๋ฐ ๊ณต๋ถ„์‚ฐ์„ ๊ณ ๋ คํ•˜์—ฌ ์„œ๋กœ์˜ ํ•˜์œ„ ์ข…๋ฅ˜ ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.

๋ถ€๋ถ„ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์„œ๋กœ ๋‹ค๋ฅธ arity๋ฅผ โ€‹โ€‹๊ฐ€์ง„ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค (์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•ด ์ž๋™ ์ปค๋ง์„ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ MySpecialPromise<SpecialType> ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

interface MyPromise<T> extends Promise<T[]> {} ์˜ˆ์ œ์—์„œ ์ €๋Š” ์†”์งํžˆ ๋งํ•ด์•ผํ•˜๋ฉฐ,์ด ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ณต์žก ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์—†์œผ๋ฉด ์ถฉ๋ถ„ํžˆ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ~MyPromise extends ~(Promise . []) ์—ฌ๊ธฐ์„œ [] ๋Š” ๋ชฉ๋ก ์ƒ์„ฑ์ž์ด๊ณ  . ๋Š” ์ƒ์„ฑ์ž ๊ตฌ์„ฑ์ž…๋‹ˆ๋‹ค. ์ด์ œ๋Š” ์ƒ์„ฑ์ž์˜ ๊ตฌ์กฐ๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์ง€๋งŒ ๊ตฌ์„ฑ์— ๋Œ€ํ•ด์„œ๋„ ์ถ”๋ก ํ•ด์•ผํ•˜๋ฏ€๋กœ ์ƒํ™ฉ์ด ํ›จ์”ฌ ๋” ์–ด๋ ค์›Œ์ง€๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!

@ jack-williams ์ด๊ฒƒ์€ ๊ธฐ๋ณธ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. P extends Foo ํ•˜๋ฉด Foo ์— ๊ธฐ๋ณธ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ (์˜ˆ : type Foo<T = {}> = ... )๊ฐ€์žˆ๋Š” ๊ฒฝ์šฐ P ์˜ ์ข…๋ฅ˜๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋‚˜๋Š” ๊ณ ์ฐจ ์œ ํ˜•์„ ์Šน์ธํ•œ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค (์‹ค์ œ TypeScript ํ”„๋กœ์ ํŠธ์—์„œ ์œ ์šฉ ํ•  ์ˆ˜์žˆ๋Š” ์ƒํ™ฉ์ด์žˆ์—ˆ์Šต๋‹ˆ๋‹ค).

๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๊ทธ๋“ค์ด ์นด๋ ˆ๋ฅผ ์ง€์›ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐ ํ•˜์ง€ ์•Š๋Š”๋‹ค . ๋‚˜๋Š” Haskell์„ ์ข‹์•„ํ•˜์ง€๋งŒ TypeScript์™€๋Š” ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ณ ์ฐจ ์œ ํ˜•์€ ์ปค๋ง์ด๋‚˜ ๋ถ€๋ถ„ ์ ์šฉ ์—†์ด๋„ ์œ ์šฉํ•˜์ง€๋งŒ ๋ถ€๋ถ„ ์ ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ช…์‹œ์ ์ธ ๊ตฌ๋ฌธ์„ ๋ณด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด ๊ฐ™์€:

Foo<number, _>  // equivalent to `type Foo1<A> = Foo<number, A>`

@ cameron-martin

ํŽธ์ง‘ : ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์˜๊ฒฌ์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. P ์—๋Š” ๊ณ ์œ  ํ•œ ์ข…๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์— ๋”ฐ๋ผ ์ข…๋ฅ˜๊ฐ€ ๋ถ€๊ณผ๋ฉ๋‹ˆ๋‹ค. ์ œ์•ฝ ์กฐ๊ฑด์€ ํ•ญ์ƒ ๊ฐ€์žฅ ๋†’์€ ์ข…๋ฅ˜๋กœ ๊ฐ„์ฃผ๋˜๋ฏ€๋กœ Foo ๋Š” ~Foo ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. P ๋ฅผ ๋” ๋‚ฎ์€ ์ข…๋ฅ˜๋กœ ๊ฐ•์ œํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ Foo ์— ๊ธฐ๋ณธ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚˜์˜ ๊ด€์‹ฌ์€ ์นœ์ ˆํ•œ ์ถ”๋ก ์ด์ง€๋งŒ,์ด ๊ฒฝ์šฐ ~ ๋„์›€์ด๋˜์ง€ ์•Š์œผ๋ฉฐ ์™„์ „ํ•œ ์ฃผ์„์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

P ์ž์ฒด ์ข…๋ฅ˜๊ฐ€ ์žˆ์ง€ ์•Š๋‚˜์š”? ์งˆ๋ฌธ์€ ์šฐ๋ฆฌ๊ฐ€ Foo ๋ฅผ ~Foo ๋กœ ์ทจ๊ธ‰ํ•˜๊ฑฐ๋‚˜ Foo<{}> ์ทจ๊ธ‰ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด P์˜ ์ข…๋ฅ˜์— ์˜ํ•ด ๊ตฌ๋™ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ P ๋Š” ๊ธฐ๋ณธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๊ฐ•์ œํ•˜๋Š” ์œ ํ˜•์ด๋ฉฐ P ๊ฐ€ ์ƒ์„ฑ์ž * => * ์ด๋ฉด Foo ๋ฅผ ๋™์ผํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

@Pauan ๊ท€ํ•˜์˜ ์ œ์•ˆ์— ๋™์˜ํ•˜์‹ญ์‹œ์˜ค.

@ jack-williams ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ํ•˜์œ„ ์ž…๋ ฅ์˜ ๊ฐœ๋…์„ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ฒซ ๋ฒˆ์งธ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~A ๊ฐ€ ~B ์˜ ํ•˜์œ„ ์œ ํ˜•์ด๋˜๋Š” ๊ฒฝ์šฐ :

  1. (a) ๊ทธ๊ฒƒ๋“ค์€ ๋™์ผํ•œ ์ข…๋ฅ˜๋ฅผ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค (์ œ์•ฝ์ด ์•„๋‹ˆ๋ผ arity ์ธก๋ฉด์—์„œ).
  2. ๋ชจ๋“  ๋ฒ•์  ํŒŒ๋ผ๋ฏธํ„ฐ (๋‚˜) Tโ‚, Tโ‚‚, ... ์˜ ~A , A<Tโ‚, Tโ‚‚, ...> ์˜ ํ•˜์œ„ ์œ ํ˜•์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค B<Tโ‚, Tโ‚‚, ...> .

๋ฌธ์ œ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ฉด ์—ญ์„ค์ ์ด๋ฉฐ ์–ธ์–ด์— ๋งž์ง€ ์•Š๋Š” ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋กœ ๋๋‚  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฒฝ์šฐ MyPromise<T> extends Promise<T[]> ์ˆ˜๋‹จ์€ MyPromise<T> ์žˆ๋‹ค๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์œผ๋กœ ์–ด๋””๋“ ์ง€ Promise<T[]> ๊ฐ€๋Šฅํ•œ ์—†์ง€๋งŒ, ์ด๊ฒƒ์€ ๋” ์ด์ƒ ์‚ฌ๊ฑด์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

as ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ a : MyPromise<T> ๋ฅผ Promise<T[]> ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด ์—… ์บ์ŠคํŒ…์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์—ญ์„ค์ ์œผ๋กœ a ๋” ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ๋”ฐ๋ฅด๋Š” ๊ธฐ์กด ์ผ๋ฐ˜ ์ œ์•ฝ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์‚ฌํ•œ ํšจ๊ณผ๋ฅผ ์–ป๊ณ  ์ด์ƒํ•œ ๋™์ž‘์„ ์ผ์œผํ‚ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

function id1<A, ~P extends ~PromiseLike>(p : P<A>) : P<A>;

function id2<A, P extends Promise<A[]>>(p : P) : P {
    //ERROR - P does not extend PromiseLike<A>
    return id1(p);
}

ํƒ€์ดํ•‘๋„ ๋ถ€์ž‘์šฉ์œผ๋กœ ์ ์–ด๋„ ๋ถ€๋ถ„์ ์œผ๋กœ ๋ช…๋ชฉ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์œ ํ˜•์€ ๊ฐ‘์ž๊ธฐ ๋‹ฌ๋ผ์ง€๋ฉฐ ํ˜„์žฌ๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

type GenericNumber<T> = number;

type RegularNumber = number;

์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜, ์ˆœ์ „ํžˆ ๊ตฌ์กฐ์  ์œ ํ˜•, ๋ฉค๋ฒ„ ์ดํ•ด๊ฐ€์žˆ๋Š” ์œ ํ˜• ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ณต์žกํ•œ ๊ณต์šฉ์ฒด / ๊ต์ฐจ ์œ ํ˜•์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น ์ง€ ํ™•์‹  ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด ๊ฐœ์ธ์ ์ธ ๋Š๋‚Œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค . ์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋Š” ๊ธฐ์กด ์œ ํ˜•์„ ๋ฐ˜๋Œ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์กด์ค‘ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค . ์•ˆํƒ€๊น๊ฒŒ๋„ ์ด๊ฒƒ์€ ์ผ์ด ๋” ๋ณต์žกํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.


ํƒ€์ž… ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ํŠน๋ณ„ํ•œ ํ‘œ๊ธฐ๋ฒ•์˜ ์–ด๋–ค ์ข…๋ฅ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ ๋Š” ๊ฐœ๋ฐœ์ž์˜ 99 %๋Š” ํƒ€์ž… ์ƒ์„ฑ์ž๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅด๋Š” ๊ทธ๋“ค์— ๋Œ€ํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ํญ๊ฒฉ ์‹ถ์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฒ”์ฃผ ์ด๋ก ์˜ ๊ณ ๊ธ‰ ๊ณผ์ •์„ ์ˆ˜๊ฐ•ํ•ด์•ผํ•˜๋Š” ๋ฒ•๋ฅ ์— ๋”ฐ๋ผ Haskell๊ณผ๋Š” ๋งค์šฐ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ด์œ ๋Š” (์•ž์„œ ์–ธ๊ธ‰ ํ•œ ๊ธฐ๋ณธ ๋งค๊ฐœ ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ์™€ ๊ฐ™์ด) ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ตฌ๋ฌธ์ด ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ „ํ˜€ ์ถ”์ƒํ™” ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํŽธ์ง‘ : ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค @GregRos ํ›„์ž์˜ ์˜๊ฒฌ์„ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค!

์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋Š” ๊ธฐ์กด ์ƒ์„ฑ์ž๋ฅผ ์กด์ค‘ํ•ด์•ผํ•˜๋ฉฐ ๋ฐ˜๋Œ€ํ•˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋‹ฌ์„ฑ ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ชจ๋“  ์„ธ๋ถ€ ์‚ฌํ•ญ๊ณผ ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์‰ฌ์šด ์ง€์— ๋Œ€ํ•ด ๋‚ด ๋จธ๋ฆฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ด์œ ๋Š” (์•ž์„œ ์–ธ๊ธ‰ ํ•œ ๊ธฐ๋ณธ ๋งค๊ฐœ ๋ณ€์ˆ˜์˜ ๊ฒฝ์šฐ์™€ ๊ฐ™์ด) ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ตฌ๋ฌธ์ด ๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ์ „ํ˜€ ์ถ”์ƒํ™” ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์ด ๋” ๋‚ฎ์•„์งˆ ํ•„์š”๊ฐ€์žˆ์„ ๋•Œ๊นŒ์ง€ ํ•ญ์ƒ ๊ฐ€์žฅ ๋†’์€ ์ข…๋ฅ˜์˜ ์ œ์•ฝ์„ ๊ฐ€์ •ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์ด ๋ชจํ˜ธ ํ•  ๊ฒƒ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ฃผ์žฅ์ด ์•„๋‹ˆ๋ฉฐ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ถฉ๋ถ„ํžˆ ๊ณต์ •ํ•œ ๋‹ค๋ฅธ ์˜ˆ๊ฐ€ ์žˆ๋‹ค๋ฉด.


๋ฌธ์ œ๋Š” ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ฉด ์—ญ์„ค์ ์ด๋ฉฐ ์–ธ์–ด์— ๋งž์ง€ ์•Š๋Š” ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋กœ ๋๋‚  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์‚ฌ์‹ค ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๋Œ€์•ˆ์ด ์‹ค์ œ๋กœ ๊ตฌํ˜„ ๋  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ์šฐ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋ณต์žกํ•œ ์†”๋ฃจ์…˜์ด ์ž‘๋™ํ•œ๋‹ค๋ฉด ๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!

๋งคํ•‘ ๊ธฐ๋Šฅ์˜ ์กด์žฌ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋” ์ผ๋ฐ˜์ ์ธ ํ•˜์œ„ ์œ ํ˜• ๊ฐœ๋…์„ ๊ฐ–๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ๊ฐ€ ๊ทœ์น™์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•ด์„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

(b) ~ A์˜ ๋ชจ๋“  ์œ ํšจํ•œ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™” Tโ‚, Tโ‚‚, ...์— ๋Œ€ํ•ด ~ B์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™” Sโ‚, Sโ‚‚, ...๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

F (A, B) = (number, B)์˜ ๋งคํ•‘์ด ์ฃผ์–ด์ง€๋ฉด X๋Š” ๋‹ค์Œ ๊ฒฝ์šฐ Y์˜ ํ•˜์œ„ ์œ ํ˜•์ด๋ฉ๋‹ˆ๋‹ค.

type X = ~<A,B> = {x : B};
type Y = ~<A,B> = A extends number ? {x: B} : never;

๊ทธ๋Ÿฌ๋‚˜ X<string,number> ์€ Y<string,number> ์˜ ํ•˜์œ„ ์œ ํ˜•์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋งคํ•‘์˜ _ ์กด์žฌ _๊ฐ€ ์ถฉ๋ถ„ํ•œ ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~ A์™€ ~ B๋ฅผ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๊ณ  ~ B๊ฐ€ ~ A์— ๊ฐ€๊น๊ฑฐ๋‚˜ ~ A๊ฐ€ ~ B์˜ ํ•˜์œ„ ์œ ํ˜•์ž„์„ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด ~ A๊ฐ€ a๊ฐ€๋˜๋Š” ์ผ๋ถ€ ํ•จ์ˆ˜ ~ C๊ฐ€ ์žˆ์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. (~ B. ~ C)์˜ ํ•˜์œ„ ์œ ํ˜•์€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (C๋Š” ๋งคํผ์ž…๋‹ˆ๋‹ค). _all_ ๋งคํ•‘์˜ ๊ฒฝ์šฐ๊ฐ€๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

function id1<A, ~P extends ~PromiseLike>(p : P<A>) : P<A>;

function id2<A, P extends Promise<A[]>>(p : P) : P {
    //ERROR - P does not extend PromiseLike<A>
    return id1(p);
}

์ด ์˜ˆ์ œ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๊นŒ? ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋‚˜์˜ ๋…์„œ๋Š” id1 ๋Š” ๋ชจ๋“  _inputs_์— ๋Œ€ํ•ด PromiseLike ๋ฅผ์ฃผ๋Š” ํ•จ์ˆ˜ P ์˜ํ•ด ๊ตฌ์„ฑ๋œ ์ž…๋ ฅ์„ ๊ฐ€์ ธ์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. id2 ๋Š” A []์— Promise๋ฅผ ์ ์šฉํ•˜๋Š” ํ•˜์œ„ ์œ ํ˜•์ด์–ด์•ผํ•˜๋Š” ๊ฐ’์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. id2 ์œ ํ˜•์—์„œ id1 ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ณต๊ตฌ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ๋‹น์‹ ์˜ ์š”์ ์„ ์˜คํ•ดํ•˜๊ณ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”.

์ด๋Ÿฌํ•œ ์œ ํ˜•์€ ๊ฐ‘์ž๊ธฐ ๋‹ฌ๋ผ์ง€๋ฉฐ ํ˜„์žฌ๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ๋‚˜๋Š” ๋‹น์‹ ์˜ ์š”์ ์„ ๋†“์น˜๊ณ  ์žˆ์„์ง€๋„ ๋ชจ๋ฅด์ง€๋งŒ ๊ทธ๋“ค์ด ์–ด๋–ป๊ฒŒ ๊ฐ™์€์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์œ ํ˜•์—์„œ RegularNumber ๋ฅผ GenericNumber ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ›„์ž์— ์ธ์ˆ˜๋ฅผ ์ง€์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋งคํ•‘์˜ ์กด์žฌ๊ฐ€ ์ถฉ๋ถ„ํ•œ ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~ A์™€ ~ B๋ฅผ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๊ณ  ~ B๊ฐ€ ~ A์— ๊ฐ€๊น๊ฑฐ๋‚˜ ~ A๊ฐ€ ~ B์˜ ํ•˜์œ„ ์œ ํ˜•์ž„์„ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด ~ A๊ฐ€ a๊ฐ€๋˜๋Š” ์ผ๋ถ€ ํ•จ์ˆ˜ ~ C๊ฐ€ ์žˆ์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. (~ B. ~ C)์˜ ํ•˜์œ„ ์œ ํ˜•์€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค (C๋Š” ๋งคํผ์ž…๋‹ˆ๋‹ค). ๋‚˜๋Š” ๋ชจ๋“  ๋งคํ•‘์˜ ๊ฒฝ์šฐ๊ฐ€๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋„ค, ๋‹น์‹  ๋ง์ด ๋งž๊ณ  ๋‹น์‹ ์ด ์ œ๊ณต ํ•œ ๋ฐ˜๋ก€๋„ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐ˜๋ก€๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ์ „ํ˜€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์™€ ๋งŽ์€ ๋‹ต๋ณ€์„ ๋‹ค์‹œ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹น์‹ ์ด ๋งŽ์€ ์ผ์—์„œ ์˜ณ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋‚˜๋Š” ๋ฌธ์ œ๋ฅผ ์ž˜๋ชป๋œ ๋ฐฉ์‹์œผ๋กœ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ์ดํ•ดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์ด ๋” ๋‚ฎ์•„์งˆ ํ•„์š”๊ฐ€์žˆ์„ ๋•Œ๊นŒ์ง€ ํ•ญ์ƒ ๊ฐ€์žฅ ๋†’์€ ์ข…๋ฅ˜์˜ ์ œ์•ฝ์„ ๊ฐ€์ •ํ•œ๋‹ค๋ฉด ๊ทธ๊ฒƒ์ด ๋ชจํ˜ธ ํ•  ๊ฒƒ์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ฃผ์žฅ์ด ์•„๋‹ˆ๋ฉฐ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ถฉ๋ถ„ํžˆ ๊ณต์ •ํ•œ ๋‹ค๋ฅธ ์˜ˆ๊ฐ€ ์žˆ๋‹ค๋ฉด.

๋ชจํ˜ธํ•˜๊ฑฐ๋‚˜ ์ฐธ์กฐ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ ํ•ด์ง‘๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ ์—์„œ์ฒ˜๋Ÿผ Foo ์˜ ํ˜•์‹ ์ƒ์„ฑ์ž๋Š” ํ˜•์‹ ์ž์ฒด์— ์˜ํ•ด ์ˆจ๊ฒจ์ ธ ์žˆ์œผ๋ฏ€๋กœ ์ฐธ์กฐ ํ•  ์ˆ˜ ์—†๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ~Foo ๋˜๋Š” ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•ด Foo<*> ๋˜๋Š” ~<A>Foo<A> ๋˜๋Š” ๋‹ค๋ฅธ ํ•ญ๋ชฉ๊ณผ ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ํ•ญ๋ชฉ์„ ์ž‘์„ฑํ•˜๋ฉด ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์˜ˆ, ๋ณ„๋ช…์„ ์ •์˜ํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

type Foo2<T> = Foo<T>

์ œ๊ฐ€ ๋งํ–ˆ๋“ฏ์ด, ์ด๊ฒƒ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ด€์‹ฌ์‚ฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ์ฝ์€ ๋‚ด์šฉ์€ id1์ด ๋ชจ๋“  ์ž…๋ ฅ์— ๋Œ€ํ•ด PromiseLike๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜ P์— ์˜ํ•ด ๊ตฌ์„ฑ๋œ ์ž…๋ ฅ์„ ๊ฐ€์ ธ์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. id2๋Š” A []์— Promise๋ฅผ ์ ์šฉํ•˜๋Š” ํ•˜์œ„ ์œ ํ˜•์ด์–ด์•ผํ•˜๋Š” ๊ฐ’์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. id2 ์œ ํ˜•์—์„œ id1์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ณต๊ตฌ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ๋‹น์‹ ์˜ ์š”์ ์„ ์˜คํ•ดํ•˜๊ณ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”.

๋งž์Šต๋‹ˆ๋‹ค. ์˜ˆ. ๊ทธ๋Ÿฌ๋‚˜ P extends Promise<A[]> ์ด๋ฉด id1 ์™€ ๊ฐ™์ด Promise<A[]> ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋ชจ๋“  ์žฅ์†Œ์— ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์ง€๊ธˆ์˜ ๋ฐฉ์‹์ด๋ฉฐ ์„œ๋ธŒ ํƒ€์ดํ•‘์˜ ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

๋” ์ด์ƒ ํ”ผํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ๋‚˜๋Š” ๋‹น์‹ ์˜ ์š”์ ์„ ๋†“์น˜๊ณ  ์žˆ์„์ง€๋„ ๋ชจ๋ฅด์ง€๋งŒ ๊ทธ๋“ค์ด ์–ด๋–ป๊ฒŒ ๊ฐ™์€์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ํ˜•์‹์—์„œ RegularNumber๋ฅผ GenericNumber๋กœ ๋ฐ”๊ฟ€ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ํ›„์ž์— ์ธ์ˆ˜๋ฅผ ์ง€์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” GenericNumber<T> ์œ ํ˜•, ๋ชจ๋“  T ๋ฐ ์œ ํ˜• RegularNumber ๋Š” ๋™์ผํ•˜๊ณ  ์ƒํ˜ธ ๊ตํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” check๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ž…๋ ฅํ•˜์ง€ ์•Š๋Š” ์ปจํ…์ŠคํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ์€ ์ ์–ด๋„.

์šฐ๋ฆฌ๊ฐ€ ์ด์•ผ๊ธฐ ํ•œ ๊ฒƒ์€ ๊ทธ๊ฒƒ๋“ค์„ ๋‹ค๋ฅด๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. GenericNumber<T> ๋Š” ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž์˜ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— RegularNumber ์ด (๊ฐ€) ๋  ์ˆ˜์—†๋Š” ๊ณณ์—์„œ๋„ ๊ฒ€์ƒ‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋” ์ด์ƒ ์ƒํ˜ธ ๊ตํ™˜ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด ๋ณด์•˜๊ณ  ๊ทธ๊ฒƒ์€ ํ”ผํ•  ์ˆ˜ ์—†์„ ์ˆ˜๋„ ์žˆ๊ณ  ๋ฐ˜๋“œ์‹œ ๋‚˜์œ ๊ฒƒ์€ ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กญ๊ณ  ๋‹ค๋ฅธ ํ–‰๋™์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์œ ํ˜•์˜ "๊ตฌ์กฐ"์˜ ์ผ๋ถ€๊ฐ€๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ข€ ๋” ๋‹ค๋ฅธ ํ–‰๋™์œผ๋กœ ์ด์–ด์งˆ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ๋ฐฉํ–ฅ

์šฐ์„ , ์˜ฌ๋ฐ”๋ฅธ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๊ฐ€ ๋งคํ•‘์ด์—†๋Š” ๊ด€๊ณ„๋ผ๋Š” ์ ์—์„œ ์˜ณ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์ฒซ ๋ฒˆ์งธ ์•„์ด๋””์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~A ๊ฐ€ ~B ์˜ ํ•˜์œ„ ์œ ํ˜•์ด๋˜๋Š” ๊ฒฝ์šฐ :

  1. (a) ๊ทธ๊ฒƒ๋“ค์€ ๋™์ผํ•œ ์ข…๋ฅ˜๋ฅผ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค (์ œ์•ฝ์ด ์•„๋‹ˆ๋ผ arity ์ธก๋ฉด์—์„œ).
  2. ๋ชจ๋“  ๋ฒ•์  ํŒŒ๋ผ๋ฏธํ„ฐ (๋‚˜) Tโ‚, Tโ‚‚, ... ์˜ ~A , A<Tโ‚, Tโ‚‚, ...> ์˜ ํ•˜์œ„ ์œ ํ˜•์ด์–ด์•ผํ•ฉ๋‹ˆ๋‹ค B<Tโ‚, Tโ‚‚, ...> .

๋งคํ•‘ ๋ฌธ์ œ๋Š” ... ์†”์งํžˆ, ๊ฝค ๋ฉ์ฒญํ•ฉ๋‹ˆ๋‹ค. ๋” ์ด์ƒ MyPromise<T> extends Promise<T[]> ์™€ ~Promise ๋ฅผ ํ†ตํ•ฉ ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์ƒ๊ฐํ•˜๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ด ๊ทœ์น™์กฐ์ฐจ๋„ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ณณ์—์„œ ๋ˆ„๋ฝ ๋œ ์˜ˆ๊ฐ€ ์žˆ๋Š”์ง€๋„ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

ํ˜•์‹ ์ƒ์„ฑ์ž ์ œ์•ฝ ์กฐ๊ฑด์ด ๋งค์šฐ ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ํ•˜์œ„ ํ˜•์‹ ๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„๋˜์–ด์•ผํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋ฌธ ์ •๋ณด

์šฐ๋ฆฌ๋Š”์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ์ •๋ง๋กœ ๋™์˜ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ~Promise ์™€ ์œ ์‚ฌํ•œ ์ ‘๋‘์‚ฌ ๊ตฌ๋ฌธ์„ ๊ฐ•๋ ฅํžˆ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋…์ ์œผ๋กœ ~ ๋Š” "TC์— ๋Œ€ํ•œ ์ฐธ์กฐ"์—ฐ์‚ฐ์ž ๋˜๋Š” ๊ทธ ๋ฐ–์˜ ๊ฒƒ์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€์•ˆ๋ณด๋‹ค ๋‚˜์€ ์ด์œ ๋ฅผ ๋ช‡ ๊ฐ€์ง€ ์ œ์‹œํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

  1. ์™„์ „ํžˆ ๋ชจํ˜ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    1. ์ด ๊ตฌ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ์˜ค๋ฅ˜๋„ ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€ ์œ ํ˜•์„ ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™”ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์€ ๊ฒฝ์šฐ ์œ ํ˜• ์ƒ์„ฑ์ž๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ชจ๋ฅผ ๋•Œ ์œ ํ˜• ์ƒ์„ฑ์ž์— ๋Œ€ํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    2. ๋ถ€์ž‘์šฉ์œผ๋กœ ๊ธฐ์กด ์˜ค๋ฅ˜ ํ…์ŠคํŠธ ๋ฐ ๋…ผ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€ Promise ์“ฐ๋ฉด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” ์ง€๊ธˆ๊ณผ ๋˜‘๊ฐ™์Šต๋‹ˆ๋‹ค. ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

  2. ๊ตฌ์กฐ์  ๊ตฌ๋ฌธ์œผ๋กœ ์ž˜ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.
  3. ํŒŒ์‹ฑํ•˜๊ธฐ ์‰ฝ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ ํ˜•์ด ์˜ˆ์ƒ๋˜๋Š” ๊ณณ์— ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ๋“  ~\w ๋Š” TC์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.
  4. ์ž…๋ ฅํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์˜๊ฒฌ์„ ์ค„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๊ณต์šฉ์ฒด, ๊ต์ฐจ์  ๋ฐ ๊ธฐ๋ณธ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ •๋ณด

* & (* => *) , * | (* => *) ๋“ฑ์˜ ์˜ค๋ฒ„๋กœ๋“œ / ํ˜ผํ•ฉ ๋œ ์ข…๋ฅ˜๊ฐ€ ํ•ฉ๋ฒ•์ ์ธ๊ฐ€์š”? ํฅ๋ฏธ๋กœ์šด ์šฉ๋„๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ๊ทธ๋“ค์ด ๋‚˜์œ ์ƒ๊ฐ์ด๊ณ  ์ถ”๋ก ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์œ ํ˜•์„ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ๋„๋ก * | (* => *) ๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ค ์ข…๋ฅ˜์˜ ์ฃผ์„์ด ํ•„์š”ํ•œ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ข…๋ฅ˜๊ฐ€ ํ˜„์žฌ ์กด์žฌํ•œ๋‹ค๊ณ  ๋งํ•  ์ˆ˜์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ๊ธฐ๋ณธ ํ˜•์‹ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ˜•์‹์ž…๋‹ˆ๋‹ค.

type Example<A = number> = {}

์ด ์œ ํ˜•์€ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ํ—ˆ์šฉ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— * & (* => *) ์œ ํ˜•์„ ๊ฐ–๋Š”๋‹ค ๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฐ˜๋“œ์‹œ ๊ทธ๋Ÿด ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ํ˜•์‹ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ํ˜•์‹์„ ์„ค๋ช…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ์†๊ธฐ ํ˜•์‹์ด์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ ํ˜•์˜ ์ข…๋ฅ˜๋ฅผ ๊ฒฐ์ •ํ•  ๋•Œ ๊ธฐ๋ณธ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๋ฌด์‹œํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ~Promise | ~Array ์™€ ๊ฐ™์€ ์œ ํ˜•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ๊ฐ™์€ ์ข…๋ฅ˜์ด๋ฏ€๋กœ ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด ์ง€์› ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐ

์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒƒ

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ด€๋ จ ์ƒํ™ฉ์„ ์ฒ˜๋ฆฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

type Example = (<~P extends ~Promise>() => P<number>) | (<~M extends ~Map>() => Map<string, number>);

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์‹ค์ œ๋กœ (* => *) | (*, *) => * ์ข…๋ฅ˜๋ฅผ ํฌํ•จํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ๋‹ค๋ฅธ

๋‹ค๋ฅธ ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž๋ฅผ ๊ตฌ์„ฑ ํ•˜์‹œ๋‚˜์š”?

์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด * => (* => *) ์™€ ๊ฐ™์ด ๋‹ค๋ฅธ ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž๋ฅผ ๋ณด์œ ํ•˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ปค๋ง ๋“ฑ์„ ์ง€์›ํ•˜๋Š” ์–ธ์–ด์—์„œ๋Š” ํ‘œ์ค€์ด์ง€๋งŒ TypeScript์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

~ ๊ตฌ๋ฌธ๊ณผ ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ์œ ํ˜•์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ „ํ˜€ ์—†์œผ๋ฏ€๋กœ์ด๋ฅผ ๊ธˆ์ง€ํ•˜๊ธฐ์œ„ํ•œ ํŠน๋ณ„ํ•œ ๊ทœ์น™์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž‘๋™ํ•˜๋ ค๋ฉด ํŠน๋ณ„ํ•œ ๊ทœ์น™์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์กฐ์ ์œผ๋กœ ์ •์˜ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

~<A>~<B>{a : A, b : B}

๊ทธ๊ฒƒ์ด ์ œ๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ƒ์œ„ ๊ธฐ๋Šฅ๊ณผ์˜ ์ƒํ˜ธ ์ž‘์šฉ?

์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜ ์œ ํ˜•๊ณผ ์ž์—ฐ ์Šค๋Ÿฝ์ง€๋งŒ ๋ณต์žกํ•œ ์ƒํ˜ธ ์ž‘์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

type Example<T> = <~P extends ~Promise>(p : P<T>) : P<T>;

์ด ์ƒํ˜ธ ์ž‘์šฉ์„ ์–ด๋–ป๊ฒŒ ๋“  ์ค‘์ง€ํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ? ์ด๋Ÿฌํ•œ ์œ ํ˜•์ด ๋งค์šฐ ๋ณต์žก ํ•ด์ง€๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ TC ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์•„์•ผํ•˜๋Š” ์žฅ์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚ด ๊ตฌ์กฐ์  ๊ตฌ๋ฌธ์ด ์ข‹์€ ์ƒ๊ฐ์ž…๋‹ˆ๊นŒ?

๋‹น์žฅ ๊ตฌํ˜„๋˜์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ตฌ์กฐ์  ๊ตฌ๋ฌธ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ๋‹ค๋ฅธ ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜์™€ ๊ฐ™์€ ๋กœ์ปฌ ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  2. ~<A>Map<string, A> , ~<A, B>Map<B, A> ๋“ฑ ๋งค์šฐ ๋ช…์‹œ์ ์ด๊ณ  ์œ ์—ฐํ•œ ๋ฐฉ์‹์œผ๋กœ ์œ ํ˜• ์ƒ์„ฑ์ž๋ฅผ ๋ถ€๋ถ„์ ์œผ๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. ์œ ํ˜•์˜ ๋‹ค๋ฅธ ๋ชจ๋“  ์ธก๋ฉด์—๋Š” ๊ตฌ์กฐ์  ๊ตฌ๋ฌธ์ด ์žˆ์œผ๋ฏ€๋กœ TC๋„ ์ด๋Ÿฌํ•œ ๊ตฌ๋ฌธ์„ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ตœ์šฐ์ˆ˜ ์‚ฌ์šฉ์ž๋Š” ์ด๊ฒƒ์ด ์—†์ด๋„ ์™„์ „ํžˆ ์ผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ฒซ ๋ฒˆ์งธ PR์—๋Š” ์•„๋งˆ๋„ ์ฐธ์—ฌ์ž๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์กฐ๊ฑด๋ถ€ ์œ ํ˜•๊ณผ์˜ ์ƒํ˜ธ ์ž‘์šฉ

๊ธฐ๋Šฅ์ด ์กฐ๊ฑด๋ถ€ ์œ ํ˜•๊ณผ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ? ์ด๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๊นŒ?

type Example<~P extends ~PromiseLike> = ~P extends ~Promise ? 0 : 1

๋‚˜๋Š” ๋‚ด ์ž์‹ ์„ ์™„์ „ํžˆ ํ™•์‹ ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์•„์ง ์กฐ๊ฑด๋ถ€ ์œ ํ˜•์„ ์™„์ „ํžˆ ์†Œํ™”ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ณผ๋ถ€ํ•˜ ํ•ด๊ฒฐ

๋‚˜๋Š” ์ด๊ฒƒ์ดํ•˜๊ธฐ ์–ด๋ ค์šธ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์ด๊ฒƒ์€ ์„œ๋กœ ๋‹ค๋ฅธ ํ˜•ํƒœ์˜ ๊ณผ๋ถ€ํ•˜ ํ•ด๊ฒฐ์ด ๊ฒฐ๊ตญ ์„œ๋กœ ๋‹ค๋ฅธ ์œ ํ˜•์„ ๊ตฌ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ง€๊ธˆ ๋‹น์žฅ์€ ์ข‹์€ ์˜ˆ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ž˜ ์ •์˜ ๋œ ์ค‘๊ฐ„ ์–ธ์–ด๊ฐ€ TypeScript๋ฅผ ์‹œ์ž‘์ ์œผ๋กœ ์„ค๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ ๋˜์—ˆ๋‹ค๋ฉด ์ด๊ฒƒ์˜ ๋Œ€๋ถ€๋ถ„์€ ๋…ผ์Ÿ ์ ์ด๋˜์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ : System F <: ๋˜๋Š” Simplified Dependent ML ๊ณผ ๊ฐ™์€ ์‚ฌ์šด๋“œ ์ข…์† ์œ ํ˜• ์‹œ์Šคํ…œ ์ค‘ ํ•˜๋‚˜.

์ด๊ฒŒ ์ „์— ํ•ด๊ฒฐ๋œ๋‹ค๋ฉด ์†”์งํžˆ ๋†€๋ผ ๊ฒ ์–ด
https://github.com/Microsoft/TypeScript/issues/14833

๋‚˜๋Š” # 17961์ด ์•„๋งˆ๋„ ์ด๊ฒƒ์„ ๊ฐ„์ ‘์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ์š”์  ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

Bifunctor ๋ฐ Profunctor ์œ ํ˜•์€ ์ œ์•ฝ ์ˆ˜์ค€์—์„œ ์•ฝ๊ฐ„ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. infer T ๋Œ€์‹  ์ž‘์—… ํ•  ๋ช…๋ฐฑํ•œ ๋ฒ”์šฉ ์œ ํ˜•์ด ์žˆ๋‹ค๋ฉด ํ›จ์”ฌ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค this ๋ฅผ "return"์œ ํ˜• (์ˆœ์ˆ˜ํ•œ ์œ ํ˜• ์ˆ˜์ค€)์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฌ์›Œ ์กŒ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

(์ €๋Š” ๋ฌด๊ฑฐ์šด TS ์‚ฌ์šฉ์ž๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ˆ˜๋ฅผํ–ˆ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @ tycho01 ์ œ๊ฐ€ ์œ ํ˜• ์—‰๋ง์ด ๋œ ๊ณณ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด

@isiahmeadows @ tycho01 ์™€์šฐ ...

๋„ค๊ฐ€ ์˜ณ์•„. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ•˜๋ฉด ๊ฑฐ์˜ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ๋Šฅ์ ์œผ๋กœ๋Š” ๊ฑฐ์˜ ๋™์ผํ•˜๋ฉฐ ์ด๋Ÿฌํ•œ ์ฐจ์ด๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜• ํ•จ์ˆ˜๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์—†์Œ

function example<~P extends ~PromiseLike>(p : P<number>) : P<string>;

์—ฌ๊ธฐ์„œ ~Bluebird ์—์„œ p ~Promise ๋ฐ ~Bluebird ๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ๊ณผ ๊ฐ™์ดํ•˜๋ฉด :

function example<F extends <T>(t: T) => PromiseLike<T>>(p : F(number)) : F(string)

์ด๊ฒƒ์ด ํšจ๊ณผ๊ฐ€ ์žˆ์„์ง€ ์˜์‹ฌ ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

example(null as Promise<number>)

F ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์Œ์„ ์œ ์ถ” ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.

<T>(t : T) => Promise<T>

์ด ๊ธฐ๋Šฅ์€ ์–ด๋–ค ์‹ ์œผ๋กœ๋“  ํŠน๋ณ„ํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. TC์™€ ๋‹ฌ๋ฆฌ ์ผ๋ถ€ ์œ ํ˜•์€ ๋ณธ์งˆ์ ์œผ๋กœ "์•”์‹œ ์ "์œ ํ˜• ์ˆ˜์ค€ ํ•จ์ˆ˜ ์ธ TC๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด TC๋ฅผ ์‰ฝ๊ฒŒ ์ฐธ์กฐ ํ•  ์ˆ˜ ์—†์Œ

๋‚ด ์ œ์•ˆ ์—์„œ์ฒ˜๋Ÿผ ~Promise ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ตฌ์กฐ์  ํ˜•์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ ํ˜•์„ ์ง์ ‘ ์ธ์ฝ”๋”ฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

type PromiseTC = <T>() => Promise<T>

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

NoInfer<T> ์˜ ์ „๋žต์ ์ธ ์‚ฌ์šฉ์„ ํ†ตํ•ด ๋ถ€๋ถ„์ ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„์ง€ ๋ชจ๋ฅด์ง€๋งŒ, ์–ด๋–ป๊ฒŒํ•ด์•ผํ•˜๋Š”์ง€, ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ์—๋„ ์–ผ๋งˆ๋‚˜ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ๋Š”์ง€ 100 % ํ™•์‹  ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฟก๋ฟก

๋‚˜๋Š” ์–ด๋–ค ๊ตฌ๋ฌธ์„ ๊ฐ•๋ ฅํžˆ ์„ ํ˜ธํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ทธ๊ฒƒ์€ ๋‚ด ์„ ํ˜ธ์— ๋” ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ~ ์—๋Š” ๋งŽ์€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”๋ก ์ด ํ•ญ์ƒ ๊ฐ€๋Šฅํ•˜์ง€๋Š” ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ช…์‹œ์ ์ธ ์ข…๋ฅ˜ ์ฃผ์„์— ๋Œ€ํ•œ ๊ตฌ๋ฌธ์ด ํ•„์š”ํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•  ์ฃผ์š” ์‚ฌํ•ญ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.


๋งคํ•‘ ๋ฌธ์ œ๋Š” ... ์†”์งํžˆ, ๊ฝค ๋ฉ์ฒญํ•ฉ๋‹ˆ๋‹ค. MyPromise๋ฅผ ํ†ตํ•ฉ ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.์•ฝ์† ์—ฐ์žฅ

๋‚˜๋Š” ๋งคํ•‘ ๊ฒƒ์€ ์—ฌ์ „ํžˆ ์œ ์šฉํ•œ ๊ฐœ๋…์ด ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, ๊ฒฝ์šฐ์— ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ํ†ตํ•ฉ์„ ์‹œ๋„ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ~MyPromise ์™€ ~Promise , ํ•„์š”์— ํ†ตํ•ฉ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ ~MyPromise ๋ฐ ~<T>Promise<T[]> ์ด๋ฉฐ ~(Promise . []) ์“ธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ˆ„๋ฝ ๋œ ์ ์€ ๋งคํ•‘์ด ํ•˜์œ„ ์œ ํ˜• ๊ด€๊ณ„์˜ ์ผ๋ถ€ ์—ฌ์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Promise ๋งŒํผ ์ƒ์„ฑ์ž์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. ์ด ์˜ˆ์—์„œ ๋งคํ•‘์€ ๋ชฉ๋ก ์ƒ์„ฑ์ž ์ผ๋ฟ์ž…๋‹ˆ๋‹ค.

interface A<T> {
    x: T;
} 

interface B<T> {
    x: T[];
}

~<T>B<T> ~<T>A<T[]> ์—ฐ์žฅํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ. ~<T>B<T> ~<T>A<T> ์—ฐ์žฅํ•ฉ๋‹ˆ๊นŒ? ์•„๋‹ˆ์š”.ํ•˜์ง€๋งŒ ๊ถ๊ทน์ ์œผ๋กœ ๋‘ ๊ฐ€์ง€ ๊ด€๋ จ์—†๋Š” ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ˜•์‹ ์ƒ์„ฑ์ž ์ œ์•ฝ ์กฐ๊ฑด์ด ๋งค์šฐ ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ํ•˜์œ„ ํ˜•์‹ ๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„๋˜์–ด์•ผํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ, ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์‚ฌ๋ฌผ์„ ์„ค๋ช…ํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ• ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.


์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜• ํ•จ์ˆ˜๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์—†์Œ

function example<~P extends ~PromiseLike>(p : P<number>) : P<string>;
์—ฌ๊ธฐ์—์„œ p์—์„œ ~Promise ๋ฐ ~Bluebird ๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์œ ํ˜• ๊ฒ€์‚ฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์™„์ „ํžˆ ํ™•์‹ ํ•˜์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์žฅ์ด ์•„๋‹ˆ๋ฉฐ ๋” ์—ด๋ฆฐ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. ์œ„์˜ ์ธํ„ฐํŽ˜์ด์Šค A ์˜ˆ๋กœ ๋“ค์–ด A<number> ๋ฐ {x: number} ์€ ๊ตฌ๋ณ„ ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ƒ์„ฑ์ž๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์žˆ์„์ง€ ํ™•์‹ ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ์ž์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฐ˜ํ™˜ ๋œ ํ˜•์‹์—์„œ P<number> ์—์„œ P ๋ฅผ ํšŒ์ˆ˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์ƒํ™ฉ์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ง€๊ธˆ ๋ฌด์—‡์„ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

# 17961์˜ ๊ต์ฐจ ์‘๋‹ต์ด์ง€๋งŒ, ๋ถˆํ–‰ํžˆ๋„ @isiahmeadows ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์ž‘๋™ํ•˜๋„๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์œ ํ˜• ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์—ญ ์ถ”๋ก ์ด ์‚ฌ์†Œํ•˜์ง€ ์•Š์„๊นŒ ๋‘๋ ต์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ž…๋ ฅ์— ๋”ฐ๋ผ ๋ชจ์–‘ Promise<number> ๋˜๋Š” Bluebird<number> ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์˜ˆ์™€ ์žฌ์‹ ๋“ค์„ ์ˆ˜์žˆ๋Š” ๋“ฑ ์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ์ ์šฉ๋˜์ง€ ์•Š์€ ๋ฒ„์ „ ์ถ”๋ก  ํ•  ์ˆ˜ ์‹ถ์–ด string . ๊ทธ๋ž˜๋„ ํž˜๋“  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ž…๋ ฅ ์œ ํ˜•์ด ๊ตฌ์กฐ์ ์œผ๋กœ ๋™๋“ฑํ•œ ๊ฒƒ ๋Œ€์‹ ์— ์ด์™€ ๊ฐ™๋”๋ผ๋„ (์šฐ๋ฆฌ๋Š” ๊ตฌ์กฐ์ ์œผ๋กœ ์œ ํ˜•ํ™” ๋œ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ๋งž์Šต๋‹ˆ๊นŒ?), ์˜ˆ๋ฅผ ๋“ค์–ด Bluebird ๋Œ€์‹  ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ ์œ ํ˜•์ด์žˆ๋Š” ๊ฒฝ์šฐ์ด ์ถ”๋ก ๋„ ๋ชจํ˜ธํ•ด์ง‘๋‹ˆ๋‹ค <string> ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋” ์ด์ƒ ์˜๋ฏธ๊ฐ€ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฑฐ๊ธฐ์— ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (๋ฉด์ฑ… ์กฐํ•ญ : ์—ฌ๊ธฐ์„œ ๋…ผ์˜์—์„œ ์•ฝ๊ฐ„ ๋’ค์ณ์กŒ์Šต๋‹ˆ๋‹ค.)

@ tycho01 ์‚ฌ๋žŒ๋“ค์ด T ๋ช…์‹œ ์ ์œผ๋กœ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋ฉด์ด ๋ชจ๋“  ๋ฌธ์ œ๊ฐ€ ์‚ฌ๋ผ์งˆ๊นŒ ์š”?

์–ด์จŒ๋“  ๋ชจ๋“  ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์ถ”๋ก ์ด ํ•ด๊ฒฐ ๋  ์ˆ˜ ์žˆ์„์ง€ ์˜์‹ฌ ์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๊ฒƒ์€ ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@ jack-williams : ์ง€๊ธˆ๊นŒ์ง€ # 17961์€ ์•„๋‹ˆ์ง€๋งŒ ๋””์ŠคํŒจ์น˜๋ฅผ โ€‹โ€‹์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋„์›€์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

let arr = [1, 2, 3];
let inc = (n: number) => n + 1;
let c = arr.map(inc); // number[]
let map = <Functor extends { map: Function }, Fn extends Function>(x: Functor, f: Fn) => x['map'](f); // any on 2.7 :(
let e = map(arr, inc);

@ tycho01 ์˜ˆ, T ๊ฐ€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์—์„œ ์ธ์Šคํ„ด์Šคํ™”๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด ์ œ์•ˆ์ด ๋”์ฐํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ž‘์—…์„ ์›ํ•˜์‹ญ๋‹ˆ๊นŒ?

interface TyCon<A> {
    C: <A>(x: A) => TyCon<A>
}

interface Functor<A> extends TyCon<A> {
    C: <A>(x: A) => Functor<A>;
    fmap<B>(this: this["C"](A), f: (x: A) => B): this["C"](B);
}

interface Option<A> extends Functor<A> {
    C: <A>(x: A) => Option<A>;
}

@ jack-williams ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด fp-ts ์˜ ADT ๊ตฌํ˜„๊ณผ ๋™์ž‘๋ฉด์—์„œ ์–ด๋–ป๊ฒŒ ๋น„๊ต๋˜๋Š”์ง€์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด๋˜์–ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ์ž‘๋™ ํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ์•„๋งˆ๋„ TyCon ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@ jack-williams @isiahmeadows :

์ด๋ฏธ $Call ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ try flow ์—์„œ ์•„์ด๋””์–ด๋ฅผ

interface Functor<A> {
    C: <A>(x: A) => Functor<A>;
    fmap<B>(f: (x: A) => B): $Call<$ElementType<this, "C">, B>;
}
// this: $Call<$ElementType<this, "C">, A>, 
// ^ flow doesn't seem to do `this` params

interface Option<A> extends Functor<A> {
    C: <A>(x: A) => Option<A>;
}

let o: Option<string>;
let f: (s: string) => number;
let b = o.fmap(f);

@ tycho01 ํ๋ฆ„์—์„œ this ์—์„œ $ElementType ๋กœ ์†์„ฑ์„ ์–ป์„ ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@ tycho01 ์‹ค์ œ๋กœ ํƒ€์ดํ”„ ์Šคํฌ๋ฆฝํŠธ์—์„œ๋„ ์ž‘๋™ํ•˜๋„๋ก ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
ํ”Œ๋ ˆ์ด ๊ทธ๋ผ์šด๋“œ : https://goo.gl/tMBKyJ

@goodmind : ํ , Functor ์—์„œ Maybe fmap ๋ณต์‚ฌ ํ•œ ํ›„ Functor<number> Maybe<number> ๋Œ€์‹ 
์œ ํ˜• ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ ํ˜•์— ๋Œ€ํ•œ ๋Ÿฐํƒ€์ž„ ๊ตฌํ˜„์ด ํ•„์š”ํ•˜์ง€ ์•Š๊ณ  ์œ ํ˜• ๋งŒ์žˆ๋Š” ๊ฒƒ์ด ํ–ฅ์ƒ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
์ด์ œ functor๋Š” ์ด๋ฏธ ์ž์ฒด fmap ๊ตฌํ˜„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ํŒŒ์ƒ ๋œ ๋ฉ”์„œ๋“œ ๋Š” ์งœ์ฆ๋‚˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.
์›์ ์œผ๋กœ ๋Œ์•„๊ฐ€๋‹ค. : /

https://github.com/SimonMeskens/TypeProps/issues/1 ์—์„œ ๋ช‡ ๊ฐ€์ง€ ๊ด€๋ จ ์•„์ด๋””์–ด

์ตœ๋Œ€ํ•œ ๋นจ๋ฆฌ ์•ŒํŒŒ ๋ฒ„์ „์„ ์ถœ์‹œ ํ•  ๊ณ„ํš์ด์ง€๋งŒ, ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์˜ˆ์ œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ €์™€ ํ•จ๊ป˜ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ฐธ๊ณ ๋กœ # 23809์—์„œ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ๋งค์šฐ ๋ถˆ์™„์ „ํ•˜์ง€๋งŒ ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

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

type unknown = {} | null | undefined;

// Functor
interface StaticFunctor<G> {
    map<F extends Generic<G>, U>(
        transform: (a: Parameters<F>[0]) => U,
        mappable: F
    ): Generic<F, [U]>;
}

// Examples
const arrayFunctor: StaticFunctor<any[]> = {
    map: <A, B>(fn: (a: A) => B, fa: A[]): B[] => {
        return fa.map(fn);
    }
};
const objectFunctor: StaticFunctor<object> = {
    map: <A, B>(fn: (a: A) => B, fa: A): B => {
        return fn(fa);
    }
};
const nullableFunctor: StaticFunctor<object | null | undefined> = {
    map: <A, B>(
        fn: (a: A) => B,
        fa: A | null | undefined
    ): B | null | undefined => {
        return fa != undefined ? fn(fa) : fa;
    }
};

const doubler = (x: number) => x * 2;

const xs = arrayFunctor.map(doubler, [4, 2]); // xs: number[]
const x = objectFunctor.map(doubler, 42); // x: number
const xNull = nullableFunctor.map(doubler, null); // xNull: null
const xSome = nullableFunctor.map(doubler, 4 as number | undefined); // xSome: number | undefined

const functor: StaticFunctor<unknown | any[]> = {
    map(fn, fa) {
        return Array.isArray(fa)
            ? arrayFunctor.map(fn, fa)
            : fa != undefined
                ? objectFunctor.map(fn, fa)
                : nullableFunctor.map(fn, fa);
    }
};

const ys = functor.map(doubler, [4, 2]); // ys: number[]
const y = functor.map(doubler, 42); // y: number
const yNull = functor.map(doubler, null); // yNull: null
const ySome = functor.map(doubler, 42 as number | undefined); // ySome: number | undefined

// Plumbing
interface TypeProps<T = {}, Params extends ArrayLike<any> = never> {
    array: {
        infer: T extends Array<infer A> ? [A] : never;
        construct: Params[0][];
    };
    null: {
        infer: null extends T ? [never] : never;
        construct: null;
    };
    undefined: {
        infer: undefined extends T ? [never] : never;
        construct: undefined;
    };
    unfound: {
        infer: [NonNullable<T>];
        construct: Params[0];
    };
}

type Match<T> = T extends infer U
    ? ({} extends U ? any
        : TypeProps<U>[Exclude<keyof TypeProps, "unfound">]["infer"]) extends never
    ? "unfound"
    : {
        [Key in Exclude<keyof TypeProps, "unfound">]:
        TypeProps<T>[Key]["infer"] extends never
        ? never : Key
    }[Exclude<keyof TypeProps, "unfound">] : never;


type Parameters<T> = TypeProps<T>[Match<T>]["infer"];

type Generic<
    T,
    Params extends ArrayLike<any> = ArrayLike<any>,
    > = TypeProps<T, Params>[Match<T>]["construct"];

์ƒ˜ํ”Œ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๋‹จ์ˆœํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ํ”Œ๋ ˆ์ด ๊ทธ๋ผ์šด๋“œ ๋งํฌ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
์šด๋™์žฅ

์œ„์˜ NPM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋” ์‰ฝ๊ฒŒ ์ž‘์—… ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์ ˆํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐ›๊ธฐ ์ „๊นŒ์ง€๋Š” ํ˜„์žฌ ์•ŒํŒŒ ๋ฒ„์ „์ด์ง€๋งŒ HKT๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Github ๋งํฌ

์กฐ๊ฑด๋ถ€ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ ํฌํ™” ์œ ํ˜• ๋‚ด์—์„œ ๊ฐ€์ƒ ์œ ํ˜• ๋ณ€์ˆ˜๋ฅผ ๋Œ€์ฒดํ•˜์—ฌ HKT๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด ์™”์Šต๋‹ˆ๋‹ค.

declare const index: unique symbol;

// A type for representing type variables
type _<N extends number = 0> = { [index]: N };

// Type application (substitutes type variables with types)
type $<T, S, N extends number = 0> =
  T extends _<N> ? S :
  T extends undefined | null | boolean | string | number ? T :
  T extends Array<infer A> ? $Array<A, S, N> :
  T extends (x: infer I) => infer O ? (x: $<I, S, N>) => $<O, S, N> :
  T extends object ? { [K in keyof T]: $<T[K], S, N> } :
  T;

interface $Array<T, S, N extends number> extends Array<$<T, S, N>> {}

// Let's declare some familiar type classes...

interface Functor<F> {
  map: <A, B>(fa: $<F, A>, f: (a: A) => B) => $<F, B>;
}

interface Monad<M> {
  pure: <A>(a: A) => $<M, A>;
  bind: <A, B>(ma: $<M, A>, f: (a: A) => $<M, B>) => $<M, B>;
}

interface MonadLib<M> extends Monad<M>, Functor<M> {
  join: <A>(mma: $<M, $<M, A>>) => $<M, A>;
  // sequence, etc...
}

const Monad = <M>({ pure, bind }: Monad<M>): MonadLib<M> => ({
  pure,
  bind,
  map: (ma, f) => bind(ma, a => pure(f(a))),
  join: mma => bind(mma, ma => ma),
});

// ... and an instance

type Maybe<A> = { tag: 'none' } | { tag: 'some'; value: A };
const none: Maybe<never> = { tag: 'none' };
const some = <A>(value: A): Maybe<A> => ({ tag: 'some', value });

const { map, join } = Monad<Maybe<_>>({
  pure: some,
  bind: (ma, f) => ma.tag === 'some' ? f(ma.value) : ma,
});

// Not sure why the `<number>` annotation is required here...
const result = map(join<number>(some(some(42))), n => n + 1);
expect(result).toEqual(some(43));

์—ฌ๊ธฐ ํ”„๋กœ์ ํŠธ : https://github.com/pelotom/hkts

ํ”ผ๋“œ๋ฐฑ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!

@pelotom ๋‚˜๋Š” ๋‹น์‹ ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ๊ตฌ๋ฌธ์˜ ๊ฐ€๋ฒผ์›€์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์—์„œ ์•„์ง ์–ธ๊ธ‰๋˜์ง€ ์•Š์€ ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ํ˜„์žฌ ๋ฐ ๋ฏธ๋ž˜ ์†”๋ฃจ์…˜์ด ์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹์— ์•ฝ๊ฐ„์˜ ์ฐฝ์˜์„ฑ์„ ๋ถˆ๋Ÿฌ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๊ฐ์ฒด ์ง€ํ–ฅ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

  1. Bertrand Meyer๋Š” ๊ทธ์˜ 1988 ๋…„ ์ €์„œ "Object-oriented Software Construction"์—์„œ ์ œ๋„ค๋ฆญ ์œ ํ˜•์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ๋Š” Eiffel์— ์žˆ์ง€๋งŒ TypeScript์— ๋Œ€ํ•œ ๋Œ€๋žต์ ์ธ ๋ฒˆ์—ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

https://gist.github.com/mlhaufe/089004abd14ad8e7171e2a122198637f

์ค‘๊ฐ„ ํด๋ž˜์Šค ํ‘œํ˜„์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋‹นํžˆ ๋ฌด๊ฑฐ์›Œ ์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ํด๋ž˜์Šค ํŒฉํ† ๋ฆฌ ํ˜•์‹์ด๋‚˜ TypeScript Mixin ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด์ด ์ž‘์—…์„ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# 17588์— ์ผ๋ถ€ ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ์ด์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋‘ ๋ฒˆ์งธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ฐ์ฒด ๋Œ€์ˆ˜ (๋ฐ ์ถ”์ƒ ํŒฉํ† ๋ฆฌ)๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

C<T> ๋Š” App<t,T> ์—ฌ๊ธฐ์„œ T ๋Š” ํด๋ž˜์Šค์ด๊ณ  t ๋Š” C ์™€ ์—ฐ๊ฒฐ๋œ ๊ณ ์œ  ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค.

interface App<C,T> {}

๊ฒฌ๋ณธ:

interface IApp<C,T> {}

interface IList<C> {
    Nil<T>(): IApp<C,T>
    Cons<T>(head: T, tail: IList<C>): IApp<C,T>
}

// defining data
abstract class List<T> implements IApp<typeof List, T> {
    // type-safe down-cast
    static prj<U>(app: IApp<typeof List, U>): List<U> { return app as List<U> }
}
class Nil<T> extends List<T> { }
class Cons<T> extends List<T> {
    constructor(readonly head: T, readonly tail: List<T>) {
        super()
    }
}

// The abstract factory where the HKT is needed
class ListFactory<T> implements IList<typeof List> {
    Nil<T>(): IApp<typeof List, T> { return new Nil() }
    Cons<T>(head: T, tail: IApp<typeof List, T>): IApp<typeof List, T> {
        return new Cons(head, tail)
    }
}

3.5 "Emulating Type-Constructor Polymorphism"์„น์…˜์˜ ๋‹ค์Œ ๋ฌธ์„œ์—์„œ ์ž์„ธํ•œ ๋‚ด์šฉ๊ณผ ํƒ€๋‹น์„ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://blog.acolyer.org/2015/08/13/streams-a-la-carte-extensible-pipelines-with-object-algebras/

@metaweta ,์ด ๋ฌธ์ œ์˜ ์ด๋ฆ„์„ Higher kinded types in TypeScript ํ•˜์—ฌ Google ๊ฒ€์ƒ‰์—์„œ ๋” ๋‚˜์€ ๊ฐ€์‹œ์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์•„๋งˆ๋„ ์šฐ๋ฆฌ์˜ ํ˜„๋ช…ํ•˜๊ณ  ์ž๋น„๋กœ์šด ์ €์žฅ์†Œ ๊ด€๋ฆฌ์ž (์˜ˆ : @RyanCavanaugh , @DanielRosenwasser )๋Š” ๊ทธ๋Ÿฌํ•œ ๋ณ€๊ฒฝ์ด ๊ฐœ์ž… ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จ๋˜๋ฉด ์ œ๋ชฉ์„ ํŽธ์ง‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์ด ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋ฐฑ ๋กœ๊ทธ๋กœ ์˜ฎ๊ฒจ ์กŒ๋‹ค๋Š” ๊ฒƒ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ•ต์‹ฌ ํŒ€์ด ์ง€๊ธˆ ๋” ์‹ฌ๊ฐํ•˜๊ฒŒ ๊ณ ๋ คํ•˜๊ณ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋‹จ์ˆœํžˆ ํŒ€์ด ์ด๊ฒƒ์ด ์ข‹์€ ์ปค๋ฎค๋‹ˆํ‹ฐ ํ›„๋ณด๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ๊ฒฐ์ •ํ–ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ?

๋ฐœ๊ฒฌ : "์ปค๋ฎค๋‹ˆํ‹ฐ"์ด์ •ํ‘œ๋Š” "๋ฐฑ ๋กœ๊ทธ"๋ฅผ ์œ„ํ•ด ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ์ด ๋ฌธ์ œ๋Š” ์•„๋งˆ๋„ ํ˜„๋ฌผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋˜์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

TS ํšŒ์›์ด ์•„๋‹ˆ๋ผ, ๋‹ค์‹œ ๋งˆ์ผ์Šคํ†ค์ด ๋œ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ์‚ฌ๋žŒ์ž…๋‹ˆ๋‹ค.

+1

๊ณ ๊ธ‰ ์œ ํ˜•์— ๋Œ€ํ•œ ์‹ค์ œ ์‚ฌ๋ก€์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ์ œ๊ฐ€ ๋ฐฉ๊ธˆ ๊ตฌ์ถ•ํ•˜๋ ค๊ณ ํ–ˆ๋˜ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

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

type Identity<T> = T

interface DatabaseStorage<Wrap<T> extends Promise<T> | Identity<T>> {
    get(key: string): Wrap<any>
    set(key: string, value: any): Wrap<void>
}

์ด๊ฒƒ์€ ์ •๋ง ๊ฐ•๋ ฅ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค!

@ccorcos ๋Š” MTL ์Šคํƒ€์ผ์ด๋ผ๊ณ ํ•ฉ๋‹ˆ๋‹ค. https://github.com/gcanti/fp-ts/blob/master/tutorials/mtl.ts ์—์„œ fp-ts ๋ฅผ ์‚ฌ์šฉํ•œ ์ˆœ์ˆ˜ ๊ธฐ๋Šฅ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@mlegenhausen ๋ฏธ์•ˆํ•˜์ง€๋งŒ ๊ทธ ์˜ˆ๋ฅผ ๋”ฐ๋ฅด๋Š” ๋ฐ ์–ด๋ ค์›€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

fp-ts ํŒŒํ—ค์น  ๋•Œ๋งˆ๋‹ค ์ƒํ™ฉ์ด ๋„ˆ๋ฌด ๋ณต์žก ํ•ด์ ธ์„œ ๋ถ€์„œ์ง€๊ธฐ ์‰ฌ์›Œ ์งˆ ๊นŒ๋ด ๊ฑฑ์ •๋ฉ๋‹ˆ๋‹ค. @pelotom ์˜ ์˜ˆ๋Š” ๋”ฐ๋ผํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค ...

์ด๊ฒƒ์ด TypeScript์— ์ฑ„ํƒ๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@ccorcos IMHO์—์„œ fp-ts ์˜ ์˜ˆ์ œ๋ฅผ ์ถ”์ฒœํ•ด๋„ MTL / ํƒœ๊ทธ์—†๋Š” ์Šคํƒ€์ผ์€ ์ „ํ˜€ ๊ถŒ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผํ•˜๋Š” ๋ชจ๋“  ํšจ๊ณผ์ ์ธ ๋ชจ๋‚˜๋“œ์— ์ถ”๊ฐ€ ์ถ”์ƒํ™” ๊ณ„์ธต์„ ์ถ”๊ฐ€ํ•˜๋ฉด typescript๊ฐ€ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๋ชจ๋‚˜๋“œ๋ฅผ ๊ฐ์ง€ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์ด ๋ณต์žกํ•ด์ง‘๋‹ˆ๋‹ค. fp-ts ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ๋ณผ ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ ํ•˜๋‚˜์˜ ๋น„๋™๊ธฐ ๋ชจ๋‚˜๋“œ ( TaskEither ๊ถŒ์žฅ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์—์„œ์กฐ์ฐจ MTL์˜ ์ด์ ์€ ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š๋Š” ์ฝ”๋“œ์—์„œ ์–ป๋Š” ๋ฒˆ๊ฑฐ ๋กœ์›€์˜ ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. fp-ts ๊ธฐ๋ฐ˜์˜ hyper-ts ๋Š” ์ตœ๊ทผ MTL ์ง€์›์„ ์ค‘๋‹จ ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค.

ํฅ๋ฏธ ๋กญ ๋„ค์š” ... hyper-ts ์ •๋ง ๋ฉ‹์ ธ ๋ณด์ž…๋‹ˆ๋‹ค ...

F-bounded polymorphism์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๊ฒฝ๋Ÿ‰์˜ ๊ณ ๊ธ‰ ์œ ํ˜• ์ธ์ฝ”๋”ฉ์„ ์ƒ๊ฐํ•ด ๋ƒˆ์Šต๋‹ˆ๋‹ค : https://github.com/strax/tshkt

์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์ด์ ์€ ํ˜•์‹ ์ƒ์„ฑ์ž๋ฅผ ํ˜•์‹์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์กฐํšŒ ํ…Œ์ด๋ธ” (๋‹จ์ผ ์กฐ๊ฑด๋ถ€ ํ˜•์‹ ๋˜๋Š” ๋ฌธ์ž์—ด ํ‚ค๊ฐ€์žˆ๋Š” ๊ฐœ์ฒด)์ด ํ•„์š” ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ธฐ์ˆ ์€ ์œ ํ˜• ์ˆ˜์ค€ ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜์˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ธ์ฝ”๋”ฉํ•˜๋Š”๋ฐ๋„ โ€‹โ€‹์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ ReturnType<<T>(value: T) => Array<T>> ).

์ด๋Š” ์—ฌ์ „ํžˆ ๊ฐœ๋… ์ฆ๋ช…์ด๋ฏ€๋กœ์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋†’์ด ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค!

์ •๋ง ๋ฉ‹์ ธ ๋ณด์ด๋Š” @strax๋ฅผ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

ํ•œํŽธ, ์ง€๊ธˆ ์šฐ๋ฆฌ๊ฐ€ ํ•  ์ˆ˜์žˆ๋Š” ์ผ์— ๋Œ€ํ•œ ์–ด๋ฆฌ์„์€ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

type Test1 = ฮป<Not, [True]>;        // False
type Test2 = ฮป<And, [True, False]>; // False
type Test3 = ฮป<And, [True, True]>;  // True

// Boolean

interface True extends Func {
    expression: Var<this, 0>;
}

interface False extends Func {
    expression: Var<this, 1>;
}

interface Not extends Func {
    expression: ฮป<Var<this, 0>, [False, True]>
}

interface And extends Func {
    expression: ฮป<Var<this, 0>, [Var<this, 1>, Var<this, 0>]>
}

// Plumbing

type Func = {
    variables: Func[];
    expression: unknown;
}

type Var<F extends Func, X extends number> = F["variables"][X];

type ฮป<Exp extends Func, Vars extends unknown[]> = (Exp & {
    variables: Vars;
})["expression"];

๋” ์ด์ƒ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์— De Bruijn ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ํŠœํ”Œ ์ˆ˜ํ•™์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ํ”ผํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

์‹ ์ฒญ

๊ณ ์ฐจ, Lamda, ์ฐธ์กฐ ์œ ํ˜•

์œ ํ˜•์„ ์ฐธ์กฐ๋กœ ์ „๋‹ฌ

๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ์ฐธ์กฐ ์œ ํ˜• ๋˜๋Š” ๋” ๋†’์€ ์ˆœ์„œ ์œ ํ˜• ์€ ๋‚˜์ค‘์— ์œ ํ˜•์ด ์ทจํ•œ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์—ฐ๊ธฐํ•˜๊ฑฐ๋‚˜ ๋‚˜์ค‘์— ์œ ํ˜• ๋งค๊ฐœ ๋ณ€์ˆ˜ (์ œ๋„ค๋ฆญ)๋ฅผ ์ถ”๋ก  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ์™œ ์‹ ๊ฒฝ์„ ์จ์•ผํ•ฉ๋‹ˆ๊นŒ?

์œ ํ˜•์„ ์ฐธ์กฐ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด TypeScript๊ฐ€ ์œ ํ˜•์„ ํ‰๊ฐ€ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•  ๋•Œ๊นŒ์ง€ ์ง€์—ฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Pipe๋กœ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

pipe ๋Œ€ํ•œ ์ œ๋„ค๋ฆญ ์œ ํ˜•์„ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ • ํ•ด๋ณด์‹ญ์‹œ์˜ค. ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์€ ํŒŒ์ดํ”„ ํ•  ํ•จ์ˆ˜๊ฐ€ ์‹ค์ œ๋กœ ํŒŒ์ดํ”„ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋งคํ•‘ ๋œ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜์—ฌ pipe(...) ์™€ ๊ฐ™์€ ํ•จ์ˆ˜ ์œ ํ˜•์„ ํŒŒ์ดํ”„ํ•ฉ๋‹ˆ๋‹ค.

type  PipeSync<Fns  extends  Function[], K  extends  keyof  Fns> = 
    K  extends  '0'
    // If it's the first function, we leave it unchanged
    ?  Fns[K]
    // For all the other functions, we link input<-output
    : (arg:  Return<Fns[Pos<Prev<IterationOf<K & string>>>]>) =>
        Return<Fns[Pos<IterationOf<K & string>>]>;

์ด์ œ ๋งคํ•‘ ๋œ ์œ ํ˜•์ด์žˆ๋Š” ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์ด๊ฒƒ์„ ๋ฐ˜๋ณตํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

type  Piper<Fns  extends  Function[]> = {
    [K  in  keyof  Fns]:  PipeSync<Fns, K>
}

( ์ „์ฒด ๊ตฌํ˜„ ์ฐธ์กฐ )

์ด์ œ ์šฐ๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ํŒŒ์ดํ”„ ํ•  ์ˆ˜ ์žˆ๊ณ  TypeScript๋Š” ๊ฒฝ๊ณ ๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

declare  function  pipe<Fns  extends  F.Function[]>(...args:  F.Piper<Fns>):  F.Pipe<Fns>

const  piped  =  pipe(
    (name:  string, age:  number) => ({name, age}),
    (info: {name:  string, age:  number}) =>  `Welcome, ${info.name}`,
    (message:  object) =>  false, // /!\ ERROR
)

ํšจ๊ณผ๊ฐ€์žˆ๋‹ค! ์ ์ ˆํ•œ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

'(message : object) => boolean'์œ ํ˜•์˜ ์ธ์ˆ˜๋Š” '(arg : string) => boolean'์œ ํ˜•์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ํ• ๋‹น ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ

ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฐ„๋‹จํ•œ ์ž‘์—…์— ๋งค์šฐ ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜์— ์ œ๋„ค๋ฆญ (ํ…œํ”Œ๋ฆฟ)์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ์™„์ „ํžˆ ์‹คํŒจํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const  piped  =  pipe(
    (a:  string) =>  a,
    <B>(b:  B) =>  b, // any
    <C>(c:  C) =>  c, // any
)

type  piped  =  Piper<[
    (a:  string) =>  string,
    <B>(b:  B) =>  B,
    <C>(c:  C) =>  C,
]>
// [
//     (a:  string) =>  string,
//     (b:  string) =>  unknown,
//     (c:  unknown) => unknown
// ]

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ TypeScript๋Š” ํ•จ์ˆ˜ ์œ ํ˜•์„ ์ถ”์ ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.
> ์ด๊ฒƒ์€ ๊ณ ์ฐจ์› ์œ ํ˜•์ด ์ž‘์šฉํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค <

ํ†ต์‚ฌ๋ก 

type  PipeSync<Fns  extends  Function[], K  extends  keyof  Fns> = 
    K  extends  '0'
    // If it's the first function, we leave it unchanged
+   ?  *(Fns[K]) // this will preserve the generics
    // For all the other functions, we link input<-output
+   :  *( // <- Any type can be made a reference
+       <T>(arg:  T) => Return<*(Fns[Pos<IterationOf<K  &  string>>])>
+       // vvv It is now a reference, we can assign generics
+       )<Return<*(Fns[Pos<Prev<IterationOf<K  &  string>>>])>>
+       // ^^^ We also tell TS not to evaluate the previous return
+       // and this could be achieved by making it a reference too

๊ฐ„๋‹จํžˆ ๋งํ•ด, * ํ•˜์—ฌ ์ œ๋„ค๋ฆญ์„ ์ˆ˜๋™ ๋ฐ ๋™์ ์œผ๋กœ ์ถ”๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ * ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ œ๋„ค๋ฆญ ํ‰๊ฐ€๊ฐ€ ์ง€์—ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ * ์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋™์ž‘์„ํ•ฉ๋‹ˆ๋‹ค. * ๊ฐ€ ๋‹ค์Œ ์œ ํ˜•์—์žˆ๋Š” ๊ฒฝ์šฐ :

  • ์ œ๋„ค๋ฆญ์„๋ฐ›์„ ์ˆ˜ ์žˆ์Œ :
  • ์ผ๋ฐ˜ ์ž์ฒด : ์ฐธ์กฐ๊ฐ€ ์•Œ๋ ค์งˆ ๋•Œ๊นŒ์ง€ ํ‰๊ฐ€๋ฅผ ์—ฐ๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ฐธ์กฐ ํŠธ๋ฆฌ๊ฐ€ ์ƒ์œ„์—์„œ ์•„๋ž˜๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ตด์ ˆ์ด ์ค‘์ฒฉ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ T ํ• ๋‹น ๋œ Return<*(Fns[Pos<Prev<IterationOf<K & string>>>])> ์ •ํ™•ํžˆ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋งฅ๋ฝ์—์„œ * ๋Š” ์ฆ‰๊ฐ์ ์ธ ํ‰๊ฐ€๋กœ๋ถ€ํ„ฐ "๋ณดํ˜ธ"ํ•œ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์œ„์˜ ์–ด๋Š ๊ฒƒ๋„ ์•„๋‹˜ : ์•„๋ฌด๊ฒƒ๋„ํ•˜์ง€ ์•Š๊ณ  ๋™์ผํ•œ ์œ ํ˜•์œผ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค.
type  piped  =  Piper<[
    (a:  string) =>  string,
    <B>(b:  B) =>  B
    <C>(c:  C) =>  C
]>
// [
//     (a:  string) =>  string,
//     (b:  string) =>  string,
//     (c:  string) =>  string
// ]

๋”ฐ๋ผ์„œ TypeScript๋Š” ์ œ๋„ค๋ฆญ์ด ์ œ๊ณต๋œ ๊ฒฝ์šฐ์—๋งŒ ํ‰๊ฐ€๋ฅผ ์‹œ์ž‘ / ๊ณ„์†ํ•˜๊ณ  ํ•„์š”ํ•  ๋•Œ ํ‰๊ฐ€๋ฅผ ์ฐจ๋‹จํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค (๋ถˆ์™„์ „ํ•œ ์ œ๋„ค๋ฆญ). ํ˜„์žฌ TS๋Š” ์ œ๋„ค๋ฆญ์„ unknown ์œ ํ˜•์œผ๋กœ ์ „ํ™˜ํ•˜์—ฌ ํ•œ ๋ฒˆ์— ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ œ์•ˆ์œผ๋กœ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜์—†๋Š” ๊ฒฝ์šฐ :

type  piped  =  Piper<[
    <A>(a:  A) =>  A, // ?
    <B>(b:  B) =>  B, // ?
    <C>(c:  C) =>  C, // ?
]>
// [
//     <A>(a:  A) =>  A,
//     (b:  A) =>  A,
//     (c:  A) =>  A
// ]

์„ธ๋ถ€

* ๋Š” ์œ ํ˜•์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ํ•ด๋‹น ์ œ๋„ค๋ฆญ์— ๋Œ€ํ•œ ์กฐ์ž‘์„ ๊ฐ€๋Šฅํ•˜๊ฒŒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ ํ˜• ์•ž์— ์™€์ผ๋“œ ์นด๋“œ๋ฅผ ๋ฐฐ์น˜ํ•˜๋ฉด ์ด์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๊ฒ€์ƒ‰๋ฉ๋‹ˆ๋‹ค.

*[type]

์œ ํ˜•์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ์ œ๋„ค๋ฆญ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

*[type]<T0, T1, T2...>

์ œ๋„ค๋ฆญ์€ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ๋Œ€์ƒ ์œ ํ˜•์— ์˜ํ•ด์„œ๋งŒ ์‚ฌ์šฉ / ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด :

*string<object, null> // Will resolve to `string`

๊ทธ๋Ÿฌ๋‚˜ ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•ด์•ผํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋Š” TypeScript ์ž์ฒด์—์„œ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๋ถ€์ ์œผ๋กœ TS๋Š”์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ * ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. C / C ++ ์–ธ์–ด์—์„œ์™€ ๊ฐ™์ด ๋ฌด์–ธ๊ฐ€์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ƒ์ง• ํ•  ์ˆ˜ ์žˆ๊ณ  TypeScript์—์„œ ์ฐจ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ณ ๋“ฑ ์ฃผ๋ฌธ ์œ ํ˜•

์ด์ œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ๋กœ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ดํŽด ๋ณด์•˜์œผ๋ฏ€๋กœ ํ•ต์‹ฌ ๊ฐœ๋… ์ธ ๋žŒ๋‹ค ์œ ํ˜• ์„ ์†Œ๊ฐœํ•˜๊ณ ์ž JavaScript์˜ ์ฝœ๋ฐฑ, ๋žŒ๋‹ค, ์ฐธ์กฐ ์™€ ์œ ์‚ฌํ•œ ์ต๋ช… ์œ ํ˜•์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์œ„์˜ ์˜ˆ๋Š” ํ•จ์ˆ˜์˜ ์ œ๋„ค๋ฆญ์„ ์ธ์ˆ˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฐธ์กฐ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— * ์™€ ํ•จ๊ป˜ ๋ชจ๋“  ์œ ํ˜•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด, ์œ ํ˜• ์ฐธ์กฐ๋Š” ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์•„์ง ์ œ๋„ค๋ฆญ์„๋ฐ›์ง€ ๋ชปํ•œ ์œ ํ˜•์ž…๋‹ˆ๋‹ค.

type  A<T  extends  string> = {0:  T}
type  B<T  extends  string> = [T]
type  C<T  extends  number> = 42

// Here's our lamda
type  Referer<*Ref<T  extends  string>, T  extends  string> =  Ref<T>
// Notice that `T` & `T` are not in conflict
// Because they're bound to their own scopes

type  testA  =  Referer<A, 'hi'> // {0: 'hi'}
type  testB  =  Referer<B, 'hi'> // ['hi']
type  testC  =  Referer<C, 'hi'> // ERROR

๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•

interface Monad<*T<X extends any>> {
  map<A, B>(f: (a: A) => B): T<A> => T<B>;
  lift<A>(a: A): T<A>;
  join<A>(tta: T<T<A>>): T<A>;
}

๊ฒ€์ƒ‰์–ด

๋” ๋†’์€ # ์ˆœ์„œ # ์œ ํ˜• # ์ฐธ์กฐ # ๋žŒ๋‹ค #HKT

@ pirix-gh ๋ฉ”์‹œ์ง€๋ฅผ ๋ช‡ ๊ฐœ๋งŒ ์ฝ์œผ๋ฉด ์š”์ฒญํ•œ ๋‚ด์šฉ์ด ์ด๋ฏธ ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ์ด๋ฏธ ์š”์ฒญ๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ๋“ค์„ ์ฝ์—ˆ๊ณ , ๋‹ค๋ฅธ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ฒ˜๋Ÿผ (์˜ฌ์ธ์› ์†”๋ฃจ์…˜์˜ ๊ฒฝ์šฐ) ๋Œ€๋ถ€๋ถ„ ๊ตฌ๋ฌธ์— ๋Œ€ํ•œ ๋‚ด ์•„์ด๋””์–ด๋ฅผ ์š”์•ฝ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฐธ์กฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋” ๋‚˜์€ ์„ค๋ช…์„ ์œ„ํ•ด ์œ„์˜ ์ œ์•ˆ์„ ํŽธ์ง‘ํ•˜๊ณ  Pipe ์™€ ๊ฐ™์€ ์œ ํ˜•์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (๋…ผ๋ฆฌ์™€ ๊ด€๋ จํ•˜์—ฌ ๋ช‡ ๊ฐ€์ง€ ์‹ค์ˆ˜๊ฐ€์žˆ์—ˆ์Šต๋‹ˆ๋‹ค).

๋ชจ๋“  ์—…๋ฐ์ดํŠธ?

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

interface Monad<T<X>> {
    map1<A, B>(f: (a: A) => B): (something: A) => B;

    map<A, B>(f: (a: A) => B): (something: T<A>) => T<B>;

    lift<A>(a: A): T<A>;
    join<A>(tta: T<T<A>>): T<A>;
}

type sn = (tmp: string) => number

function MONAD(m: Monad<Set>,f:sn) {
    var w = m.map1(f);    // (method) Monad<Set>.map1<string, number>(f: (a: string) => number): (something: string) => number
    var w2 = m.map(f);    // (method) Monad<Set>.map<string, number>(f: (a: string) => number): (something: Set<string>) => Set<number>
    var q = m.lift(1);    // (method) Monad<Set>.lift<number>(a: number): Set<number>
    var a = new Set<Set<number>>();
    var w = m.join(q);    // (method) Monad<Set>.join<unknown>(tta: Set<Set<unknown>>): Set<unknown>.  You could see that typeParameter infer does not work for now.
    var w1 = m.join<number>(q);    // (method) Monad<Set>.join<number>(tta: Set<Set<number>>): Set<number>
}

๋น ๋ฅธ ์ •๋ณด ์ˆ˜์ •, typeParameter ์ถ”๋ก , ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€, ๋™์ผํ•œ typeConstructor ๊ฐ•์กฐ ํ‘œ์‹œ์™€ ๊ฐ™์€ ๋งŽ์€ ์ž‘์—…์ด ์—ฌ์ „ํžˆ ์ˆ˜ํ–‰๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ž‘๋™ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ  ์—ฌ๊ธฐ์— ์ง€๊ธˆ ๋‹น์žฅ ์–ป์„ ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ์ œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” @millsp https://github.com/microsoft/TypeScript/issues/1213#issuecomment -523245130์ž…๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์€ ์ •๋ง ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค.

communicity๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ํ˜„์žฌ ๋ฐฉ์‹์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋งŽ์€ ์‚ฌ์šฉ์ž ์‚ฌ๋ก€๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

HKT / ํ•จ์ˆ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ / ๋žŒ๋‹ค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค ( lambda ๋ผ๊ณ  ๋งํ•˜๋ฉด ์ˆ˜ํ•™์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜ํ•™์—†์ด ์ผ๋ถ€ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ์˜ˆ์ œ ๋งŒ ์ฐพ์„ ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค)

๋‹ค์Œ์€ ์ €์—๊ฒŒ ๋งŽ์€ ๋„์›€์ด๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@ShuiRuTian m.join(q) Set<unknown> m.join(q) ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ --noImplicitAny ์ด (๊ฐ€) ๊ฒฝ๊ณ ๋ฅผ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ํ˜„์žฌ ๋ฐฉ์‹์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋งŽ์€ ์‚ฌ์šฉ์ž ์‚ฌ๋ก€๋ฅผ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

HKT / ํ•จ์ˆ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ / ๋žŒ๋‹ค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค ( lambda ๋ผ๊ณ  ๋งํ•˜๋ฉด ์ˆ˜ํ•™์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜ํ•™์—†์ด ์ผ๋ถ€ ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ์˜ˆ์ œ ๋งŒ ์ฐพ์„ ์ˆ˜์žˆ์—ˆ์Šต๋‹ˆ๋‹ค)

๋” ์ด์ƒ ์ง„ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์ตœ๊ทผ์— ์ผ๋ฐ˜์ ์ธ ์นด๋ ˆ filter ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ์‹œ๋„ํ–ˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค.

const filterNumbers = filter(
    (item: number | string): item is number => typeof item === "number"
);

const array = ["foo", 1, 2, "bar"]; // (number | string)[]
const customObject = new CustomObject(); // CustomObject<number | string>

filterNumbers(array); // number[] inferred
filterNumbers(customObjectWithFilterFunction); // CustomObject<number> inferred

๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. TypeScript์— "๋ฐ›์€ ๊ฒƒ๊ณผ ๊ฐ™์€ ์œ ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ์ด ๋‹ค๋ฅธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜ํ™˜"ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ™์€:

const filter = <Item, FilteredItem>(predicate: (item: Item) => item is FilteredItem) =>
  <Filterable<~>>(source: Filterable<Item>): Filterable<FilteredItem> => source.filter(predicate);

@lukeshiru ์˜ˆ, ๋ณธ์งˆ์ ์œผ๋กœ ์ด๊ฒƒ์€ https://pursuit.purescript.org/packages/purescript-filterable/2.0.1/docs/Data.Filterable#v : filter
TypeScript์—๋Š” HKT์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ์œ ์‚ฌํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

@isiahmeadows ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ–ˆ๋‹ค. ๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค.
@lukeshiru ๋ฐ @raveclassic ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์ด ๊ธฐ๋Šฅ์€ ๊ฝค ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://gcanti.github.io/fp-ts/learning-resources/ ๋ฅผ ์ฝ์€ ํ›„ ์ด๊ฒƒ์„ ์‚ดํŽด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ง‰ํ˜”๊ณ  ํ˜„์žฌ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค ...
์ฒด์ธ ์‚ฌ์–‘ ์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

m['fantasy-land/chain'](f)

Chain ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ’์€ Apply ์‚ฌ์–‘๋„ ๊ตฌํ˜„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

a['fantasy-land/ap'](b)

FunctorSimplex ๋ฅผ ํ•œ ๋‹ค์Œ FunctorComplex ๋กœ ํ™•์žฅ ํ•œ ๋‹ค์Œ Apply ๋กœ ํ™•์žฅํ–ˆ์ง€๋งŒ ์ด์ œ Apply ๋ฅผ Chain ๋กœ ํ™•์žฅํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค (์•„๋ž˜ ์ด๋ฏธ์ง€์™€ ์ฝ”๋“œ ๋งํฌ).

(๋‚˜๋Š” ์œ ํ˜•์„ ApType ์— ์ „๋‹ฌํ•˜์—ฌ 12 ํ–‰์—์„œ Apply ๊ฐ€ ยซํ•˜๋“œ ์ฝ”๋”ฉ ๋œยป์ด ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜ ... IApply ์—์„œ ํ™•์žฅ ๋œ ์œ ํ˜•๋„ ์ทจํ•˜๋„๋กํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Screenshot

7ff8b9c์˜ 11 ~ 22 ํ–‰ ์ฝ”๋“œ ์Šค ๋‹ˆํŽซ์— ๋Œ€ํ•œ ์˜๊ตฌ ๋งํฌ

```ํƒ€์ž… ์Šคํฌ๋ฆฝํŠธ
๋‚ด๋ณด๋‚ด๊ธฐ ์œ ํ˜• ApType = ( ap : ์ ์šฉ <(val : A) => B>, ) => IApply ;

/ * [...] * /

๋‚ด๋ณด๋‚ด๊ธฐ ์ธํ„ฐํŽ˜์ด์Šค IApply extends FunctorComplex {
/ ** Fantasy-land/ap :: Apply f => f a ~> f (a -> b) -> f b * /
ap : ApType ;
}
```

์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ ์งˆ๋ฌธ : TypeScript ์ผ๋ฐ˜ ์œ ํ˜• ๋ฌธ์ œ ์ฐธ์กฐ : ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ํ•„์š”

@Luxcium TS๊ฐ€ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•์„ ์ง€์›ํ•  ๋•Œ๊นŒ์ง€๋Š” ์—๋ฎฌ๋ ˆ์ด์…˜ ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ๋‹ฌ์„ฑ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„๋ณด๊ธฐ ์œ„ํ•ด ๊ทธ๊ณณ์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TS๊ฐ€ ๋” ๋†’์€ ์ข…๋ฅ˜์˜ ์œ ํ˜•์„ ์ง€์›ํ•  ๋•Œ๊นŒ์ง€๋Š” ์—๋ฎฌ๋ ˆ์ด์…˜ ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ฌ์„ฑ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„๋ณด๊ธฐ ์œ„ํ•ด ๊ทธ๊ณณ์„ ์‚ดํŽด๋ณด๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Tanks a lot @kapke ์š”์ฆ˜ FP์— ๋„ˆ๋ฌด ๋งŽ์ด ๋น ์ ธ ์žˆ๊ณ  Javascript์—์„œ ํ•จ์ˆ˜์—์„œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— pseudoFnAdd(15)(27) // 42 TypeScript๋กœ pseudoType<someClassOrConstructor><number> // unknown ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด ์ •๋ณด์™€ ๊ฐ•์˜ (๋…์„œ)๋Š” ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ...

์ฐธ๊ณ  : ์ €๋Š” ํ”„๋ž‘์Šค์–ด๋กœ ๋งํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ž‘์Šค์–ด๋กœ _lecture (s) _๋ผ๋Š” ๋‹จ์–ด๋Š” _readings_์˜ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ 'ํ–‰๋™์„ ๋น„ํŒํ•˜๊ธฐ ์œ„ํ•ด ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ์ฃผ์–ด์ง„ ํ™” ๋‚˜๊ฑฐ๋‚˜ ์ง„์ง€ํ•œ ๋Œ€ํ™”'๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

์•„๋งˆ๋„ PR์ด์—†๋Š” ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‚ด๊ฐ€ ์ƒ๊ฐ ํ•ด๋‚ธ ๋‹ค์Œ์€ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ ์šฉ๋˜์ง€๋Š” ์•Š์ง€๋งŒ ์–ธ๊ธ‰ ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

type AGenericType<T> = T[];

type Placeholder = {'aUniqueKey': unknown};
type Replace<T, X, Y> = {
  [k in keyof T]: T[k] extends X ? Y : T[k];
};

interface Monad<T> {
  map<A, B>(f: (a: A) => B): (v: Replace<T, Placeholder, A>) => Replace<T, Placeholder, B>;
  lift<A>(a: A): Replace<T, Placeholder, A>;
  join<A>(tta: Replace<T, Placeholder, Replace<T, Placeholder, A>>): Replace<T, Placeholder, A>;
}

function MONAD(m: Monad<AGenericType<Placeholder>>, f: (s: string) => number) {
  var a = m.map(f); // (v: string[]) => number[]
  var b = m.lift(1); // number[]
  var c = m.join([[2], [3]]); // number[]
}
์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰
bleepcoder.com์€ ๊ณต๊ฐœ์ ์œผ๋กœ ๋ผ์ด์„ ์Šค ๋œ GitHub ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „ ์„ธ๊ณ„ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” GitHub, Inc. ๋˜๋Š” ํ”„๋กœ์ ํŠธ์— GitHub๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์„œ๋ฒ„์—์„œ ๋น„๋””์˜ค ๋‚˜ ์ด๋ฏธ์ง€๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ถŒ๋ฆฌ๋Š” ํ•ด๋‹น ์†Œ์œ ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ํŽ˜์ด์ง€์˜ ์†Œ์Šค: ์ถœ์ฒ˜

์ธ๊ธฐ์žˆ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด
์ธ๊ธฐ์žˆ๋Š” GitHub ํ”„๋กœ์ ํŠธ
๋” ๋งŽ์€ GitHub ํ”„๋กœ์ ํŠธ

ยฉ 2024 bleepcoder.com - Contact
Made with in the Dominican Republic.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.