์ด๊ฒ์ ์ ๋ค๋ฆญ์ ์ ํ ๋งค๊ฐ ๋ณ์๋ก ํ์ฉํ๊ธฐ์ํ ์ ์์ ๋๋ค. ํ์ฌ ํน์ ๋ชจ๋๋ ์์ ๋ฅผ ์์ฑํ ์ ์์ง๋ง ๋ชจ๋ ๋ชจ๋๋๊ฐ ๋ง์กฑํ๋ ์ธํฐํ์ด์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด
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๊ฐ ์ ํจํ๋ ค๋ฉด ์ ์์ ๋ณ์นญ์ ๋ฐฐ์ด์ด ์ผ์นํด์ผํฉ๋๋ค.
์ฑ๊ธํ ๊ฐ์ ์ ์๋์ง๋ง ์๋ชป ์ ๋ ฅํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ชจ๋ ๋งค๊ฐ ๋ณ์ ์ ํ์๋ ๋งค๊ฐ ๋ณ์ ์ด๋ฆ์ด ํ์ํ๋ฏ๋ก
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 ๋๋ ์ง๊ธ ๋ ํฐ ๋ฌผ๊ณ ๊ธฐ๊ฐ ํ๊ธธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋๋ฐ, ๋ ๋์ ์ฐ์ ์์๋ฅผ
bind
, call
๋ฐ apply
๋ ํ์์ด ์ง์ ๋์ง ์์ต๋๋ค. ์ด๊ฒ์ ์ค์ ๋ก ๊ฐ๋ณ ์ ๋ค๋ฆญ ์ ์ ์ ๋ฌ๋ ค ์์ต๋๋ค. Object.assign
๋ ๋น์ทํ ์์ ์ด ํ์ํ์ง๋ง ๊ฐ๋ณ ์ ๋ค๋ฆญ๋ง์ผ๋ก๋ ํด๊ฒฐํ ์ ์์ต๋๋ค._.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
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
๋ฅผ ๊ตฌํํ ์์๋ ์ธ ๊ฐ์ง ์ต์
์ ๊ณ ๋ คํ์ต๋๋ค.
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
์ ํ์ ๋ค์๊ณผ ๊ฐ์ ๊ณ ์ฐจ ํํ๋ฅผ ๊ฐ์ต๋๋ค.
(* => *, (*,*) => *) => *
๊ทธ๋ฐ ๋ค์ ์์ ์ธ๊ธ ํ ๊ฒ๊ณผ ๊ฐ์ ๋ชจ์์ ํํํ ์์๋ ๋ ๋์ ๋ชจ์์ ๋ฐ๋, ๊ฐ์ฅ ์์ ํ ํํ์ ์กฐ์ฌํ์ต๋๋ค.
(* => (*,*)) => ((*,*) => *)
์ด์ ๋ํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๊ฐ๋จํ์ง๋ง TypeScript ์ ํ ์์คํ
๊ณผ ์ ์ํธ ์์ฉํ์ง ์์ต๋๋ค. ์ด๋ฌํ ๊ณ ์ฐจ ์ ํ์ ํ์ฉํ๋ค๋ฉด *
๊ฐ ๊ฐ ์
๋ ฅ์ ์ฌ์ฉ๋ ์์๋ ์ง์ ์ ํ์ ์๋ฏธํ๋์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ฝ ์ ์ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ, ๋๋ ๊ทธ๋ฌํ ๊ดด๋ฌผ ๊ฐ์ ๊ณ ์ฐจ ์ ์ฝ์ ํํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ์ ํ ๊ตฌ๋ฌธ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
์ฃผ์ ์์ด๋์ด-์ ํ ํํ์ (์ค์ ์ ํ ์ธ์ ํฌํจ)์ ํญ์ ๋ณ์๋ฅผ ์ ๋ ฅํ๋ ๋ฐ ์ฌ์ฉํ ์์๋ ์ ์ง ์ ํ์ ์์ฑํฉ๋๋ค. ๋ฐ๋ฉด์ ๊ฐ ์ ํ ๋งค๊ฐ ๋ณ์๋ ๋ค๋ฅธ ๊ณณ์์ ์ฌ์ฉ๋๋ ๊ฒ๊ณผ ๋์ผํ ํ์์ผ๋ก ๊ณ ์ ํ ์ธ๋ถ ์ ํ ๋งค๊ฐ ๋ณ์๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค.
์ด๊ฒ์ด ์ ๊ฐ ์นํธํ๋ ค๋ ์ต์ข ๊ฒฐ์ ์ด์์ต๋๋ค.
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 ํ์ดํ์
๋๋ค).
~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
์ ํ์ ์ ํ์ด๋๋ ๊ฒฝ์ฐ :
- (a) ๊ทธ๊ฒ๋ค์ ๋์ผํ ์ข ๋ฅ๋ฅผ ๊ฐ์ ธ์ผํฉ๋๋ค (์ ์ฝ์ด ์๋๋ผ arity ์ธก๋ฉด์์).
- ๋ชจ๋ ๋ฒ์ ํ๋ผ๋ฏธํฐ (๋)
Tโ, Tโ, ...
์~A
,A<Tโ, Tโ, ...>
์ ํ์ ์ ํ์ด์ด์ผํฉ๋๋คB<Tโ, Tโ, ...>
.
๊ทธ๋ฌ๋ ์ฌ๊ธฐ์๋ ๋ช ๊ฐ์ง ์ ํ ์ฌํญ์ด ์์ต๋๋ค.
MySpecialPromise ํด๋์ค ๋ PromiseLike {}๋ฅผ ๊ตฌํํฉ๋๋ค.
MyArrayPromise ํด๋์ค ์ด ๊ฒฝ์ฐ์๋ ํ์ ์ ํ ๊ด๊ณ๊ฐ ๋ณด์กด๋์ง ์์ต๋๋ค.
(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;
}
๊ตฌ๋ฌธ์๋ ๋ช ๊ฐ์ง ๋๊ธฐ๊ฐ ์์ต๋๋ค.
~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>;
}
๊ทธ๋ฐ ๋ค์ ์ ํ์ ์ผ๋ก ์กด์ฌ ์ ํ์ ์ฌ์ฉํ์ฌ ํจ์ ๋๋ ์ ํ์ ์๋ช ๋ด์์ ์์ฑ ๋ ์ ํ์ ํตํด ๋ชจ๋ ์ ํ ์์ฑ์๋ฅผ ์ ํํ๋๋ก ์๊ตฌํ ์ ์์ต๋๋ค.
์ค์กด ์ ์ ํ์ ์ฌ์ฉํ๋ฉด ๋งคํ์ด์๋ ํ์ ์ ํ ๊ด๊ณ์ ๋์ผํ ํํ๋ ฅ์ ๊ฐ๊ฒ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ฌ๋ฌ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
((* => *) => *) => *
์ ๊ฐ์ ์ข
๋ฅ๋ก ์ ํ ์์ฑ์๋ฅผ ์ง์ ํ๋ ค๋ฉด ๋ง์ ์กด์ฌ ์ ํ์ ๋์
ํด์ผํ๋ฉฐ, ๊ทธ์ค ์ผ๋ถ๋ ๋ ๋์ ์์ ์ฌ์ผํฉ๋๋ค. ๊ทธ๋ค ๋ชจ๋๋ ํจ์ ๋๋ ํด๋์ค์ ์๊ทธ๋์ฒ์ sppearํด์ผํฉ๋๋ค.๋ฟก๋ฟก
์ด๋ค ์ข ๋ฅ์ ๊ตฌ๋ฌธ์ ์ฌ์ฉ ํ์๊ฒ ์ต๋๊น? ์ด๋ค ๊ฐ๋ ์ ์ฌ์ฉ ํ์๊ฒ ์ต๋๊น?
_ ๊ฐ์ธ์ ์ผ๋ก _ ํน๋ณํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ง ์๊ณ ๋ค์์ ์ฌ์ฉํฉ๋๋ค.
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
์ ํ์ ์ ํ์ด๋๋ ๊ฒฝ์ฐ :
- (a) ๊ทธ๊ฒ๋ค์ ๋์ผํ ์ข ๋ฅ๋ฅผ ๊ฐ์ ธ์ผํฉ๋๋ค (์ ์ฝ์ด ์๋๋ผ arity ์ธก๋ฉด์์).
- ๋ชจ๋ ๋ฒ์ ํ๋ผ๋ฏธํฐ (๋)
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
์ ํ์ ์ ํ์ด๋๋ ๊ฒฝ์ฐ :
- (a) ๊ทธ๊ฒ๋ค์ ๋์ผํ ์ข ๋ฅ๋ฅผ ๊ฐ์ ธ์ผํฉ๋๋ค (์ ์ฝ์ด ์๋๋ผ arity ์ธก๋ฉด์์).
- ๋ชจ๋ ๋ฒ์ ํ๋ผ๋ฏธํฐ (๋)
Tโ, Tโ, ...
์~A
,A<Tโ, Tโ, ...>
์ ํ์ ์ ํ์ด์ด์ผํฉ๋๋คB<Tโ, Tโ, ...>
.
๋งคํ ๋ฌธ์ ๋ ... ์์งํ, ๊ฝค ๋ฉ์ฒญํฉ๋๋ค. ๋ ์ด์ MyPromise<T> extends Promise<T[]>
์ ~Promise
๋ฅผ ํตํฉ ํ ๋ฐฉ๋ฒ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ์๊ฐํ๋์ง ์๊ณ ์ถ์ต๋๋ค.
์ด ๊ท์น์กฐ์ฐจ๋ ์๋ํ์ง ์๋ ๊ณณ์์ ๋๋ฝ ๋ ์๊ฐ ์๋์ง๋ ์๊ณ ์ถ์ต๋๋ค.
ํ์ ์์ฑ์ ์ ์ฝ ์กฐ๊ฑด์ด ๋งค์ฐ ์ ์๋ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ํ์ ํ์ ๊ด๊ณ๋ฅผ ์ฌ์ฉํ์ฌ ํํ๋์ด์ผํ๋ค๋ ๋ฐ ๋์ํ๋ฉด ๋ค๋ฅธ ๊ฒ์ผ๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋์ด ์ฃผ์ ์ ๋ํด ์ ๋ง๋ก ๋์ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ~Promise
์ ์ ์ฌํ ์ ๋์ฌ ๊ตฌ๋ฌธ์ ๊ฐ๋ ฅํ ์ ํธํฉ๋๋ค. ๊ฐ๋
์ ์ผ๋ก ~
๋ "TC์ ๋ํ ์ฐธ์กฐ"์ฐ์ฐ์ ๋๋ ๊ทธ ๋ฐ์ ๊ฒ์ผ๋ก ๋ณผ ์ ์์ต๋๋ค.
๋์๋ณด๋ค ๋์ ์ด์ ๋ฅผ ๋ช ๊ฐ์ง ์ ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
Promise
์ฐ๋ฉด ์ค๋ฅ ๋ฉ์์ง๋ ์ง๊ธ๊ณผ ๋๊ฐ์ต๋๋ค. ์ต์ฐ์ ์ฌ์ฉ์์ ๋ํด ์ด์ผ๊ธฐํ๊ธฐ ์ํด ๋ณ๊ฒฝํ ํ์๊ฐ ์์ต๋๋ค.~\w
๋ TC์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ํ๋ด๋ ๊ฒ์ผ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.๋ค๋ฅธ ์ฌ๋๋ค์ด ์๊ฒฌ์ ์ค ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
* & (* => *)
, * | (* => *)
๋ฑ์ ์ค๋ฒ๋ก๋ / ํผํฉ ๋ ์ข
๋ฅ๊ฐ ํฉ๋ฒ์ ์ธ๊ฐ์? ํฅ๋ฏธ๋ก์ด ์ฉ๋๊ฐ ์์ต๋๊น?
๋๋ ๊ทธ๋ค์ด ๋์ ์๊ฐ์ด๊ณ ์ถ๋ก ํ๊ธฐ ์ด๋ ต๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ํ ์ ํ์ ๊ตฌ์ฑ ํ ์ ์๋๋ก * | (* => *)
๋ช
ํํํ๊ธฐ ์ํด ์ด๋ค ์ข
๋ฅ์ ์ฃผ์์ด ํ์ํ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ด๋ฌํ ์ข ๋ฅ๊ฐ ํ์ฌ ์กด์ฌํ๋ค๊ณ ๋งํ ์์๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๊ธฐ๋ณธ ํ์ ๋งค๊ฐ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ํ์์ ๋๋ค.
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 ๋งค๊ฐ ๋ณ์๊ฐ ํ์๋์ง ์์์ผํ๋ ์ฅ์๊ฐ ์์ต๋๊น?
๋น์ฅ ๊ตฌํ๋์ด์ผํ๋ค๊ณ ์๊ฐํ์ง๋ ์์ง๋ง ์ฌ์ ํ ๊ตฌ์กฐ์ ๊ตฌ๋ฌธ์ด ์ข์ ์๊ฐ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ค์์ ์ํ ํ ์ ์์ต๋๋ค.
~<A>Map<string, A>
, ~<A, B>Map<B, A>
๋ฑ ๋งค์ฐ ๋ช
์์ ์ด๊ณ ์ ์ฐํ ๋ฐฉ์์ผ๋ก ์ ํ ์์ฑ์๋ฅผ ๋ถ๋ถ์ ์ผ๋ก ์ ์ฉํฉ๋๋ค.์ฆ, ์ต์ฐ์ ์ฌ์ฉ์๋ ์ด๊ฒ์ด ์์ด๋ ์์ ํ ์ผํ ์ ์์ผ๋ฉฐ ์ฒซ ๋ฒ์งธ 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๋ฅผ ๊ฐ์ต๋๋ค.
๋ด ์ ์ ์์์ฒ๋ผ ~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๋ฅผ ์์ฑํ๋ ๋ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
์กฐ๊ฑด๋ถ ์ ํ์ ์ฌ์ฉํ์ฌ ํฌํ ์ ํ ๋ด์์ ๊ฐ์ ์ ํ ๋ณ์๋ฅผ ๋์ฒดํ์ฌ 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 ๋๋ ๋น์ ์ ์ ๊ทผ ๋ฐฉ์์ ๊ตฌ๋ฌธ์ ๊ฐ๋ฒผ์์ ์ข์ํฉ๋๋ค. ์ด ์ค๋ ๋์์ ์์ง ์ธ๊ธ๋์ง ์์ ๋ ๊ฐ์ง ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ด ํ์ฌ ๋ฐ ๋ฏธ๋ ์๋ฃจ์ ์ด ์์ฑ๋๋ ๋ฐฉ์์ ์ฝ๊ฐ์ ์ฐฝ์์ฑ์ ๋ถ๋ฌ ์ผ์ผํฌ ์ ์์ต๋๋ค. ๋ ๋ค์ด ๋ฌธ์ ์ ๋ํ ๊ฐ์ฒด ์งํฅ ์๋ฃจ์ ์ ๋๋ค.
์์ ๋ Eiffel์ ์์ง๋ง TypeScript์ ๋ํ ๋๋ต์ ์ธ ๋ฒ์ญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
https://gist.github.com/mlhaufe/089004abd14ad8e7171e2a122198637f
์ค๊ฐ ํด๋์ค ํํ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ์๋นํ ๋ฌด๊ฑฐ์ ์ง ์ ์์ง๋ง ํด๋์ค ํฉํ ๋ฆฌ ํ์์ด๋ TypeScript Mixin ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด์ด ์์ ์ ํฌ๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
# 17588์ ์ผ๋ถ ์ ์ฉ ๊ฐ๋ฅ์ฑ์ด์์ ์ ์์ต๋๋ค.
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 ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ง๋ง ํํ ์ํ์ด ํ์ํ๋ค๊ณ ์๊ฐํ๊ณ ํผํ๋ ค๊ณ ํฉ๋๋ค.
๊ฐ๋จํ ๋งํด์, ์ฐธ์กฐ ์ ํ ๋๋ ๋ ๋์ ์์ ์ ํ ์ ๋์ค์ ์ ํ์ด ์ทจํ ๋งค๊ฐ ๋ณ์๋ฅผ ์ฐ๊ธฐํ๊ฑฐ๋ ๋์ค์ ์ ํ ๋งค๊ฐ ๋ณ์ (์ ๋ค๋ฆญ)๋ฅผ ์ถ๋ก ํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ ์ ๊ฒฝ์ ์จ์ผํฉ๋๊น?
์ ํ์ ์ฐธ์กฐ๋ก ์ ๋ฌํ ์ ์๋ค๋ฉด TypeScript๊ฐ ์ ํ์ ํ๊ฐํ๊ธฐ๋ก ๊ฒฐ์ ํ ๋๊น์ง ์ง์ฐ์ํฌ ์ ์์ต๋๋ค. ์ค์ ์ฌ๋ก๋ฅผ ์ดํด ๋ณด๊ฒ ์ต๋๋ค.
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>;
}
@ 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
์์ ํ์ฅ ๋ ์ ํ๋ ์ทจํ๋๋กํด์ผํฉ๋๋ค.
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[]
}
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
HKT์ ์ฌ๊ณ ๋ฐฉ์์ ๋ณํ ์ ์๊ณ , ์ต๊ด์ ๊นจ์ง๊ณ , ์์ด๋ฒ๋ฆฐ ์ธ๋๋ ๋ค์ ์ด์ ๋๊ฒ๋ฉ๋๋ค.
๋ค์ ํฐ ๊ธฐ๋ฅ์ผ๋ก ์๊ฐํ์ธ์. ๋ ๋์ ๋ง์ ๊ณ์ ์๊ตฌํ๋ ์ฌ๋๋ค์ ๋ง์ ๋ฃ์ง ๋ง๊ณ , ๊ทธ๋ค์๊ฒ af * g ํ๋ผ๋ฆฌ๋ฅผ์ฃผ์ธ์