diff --git a/09_ts/05_ts-all-in-one/19.ts b/09_ts/05_ts-all-in-one/19.ts new file mode 100644 index 0000000..ad31ae6 --- /dev/null +++ b/09_ts/05_ts-all-in-one/19.ts @@ -0,0 +1,67 @@ +// bind 타입 분석 + +function sayName(this: Window | typeof user, param: string) { + console.log(this.name); +} + +const user = { name: 'wally' }; +const bindingUser = sayName.bind(user); +bindingUser('1'); // 'wally' + +// Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter. +type T = ThisParameterType; +// Removes the 'this' parameter from a function type. +type NoThis = OmitThisParameter; + + +// bind 사용 예제 + +// #1) this를 쓰는 경우 +// bind(this: T, thisArg: ThisParameterType): OmitThisParameter; 가 적용 +const wallyUser = { + name: 'wally', + sayHello(this: { name: string }) { + console.log(`hi, ${this.name}`); + } +} + +const sayHello = wallyUser.sayHello; +const sayHi = wallyUser.sayHello.bind({ name: 'wally-wally' }); +sayHi(); // 'hi, wally-wally' + +// #2) this를 안 쓰는 경우 +// 그 나머지 케이스들 (타입 분석이 헷갈리면 this parameter를 지우고 보면 편하다) +// bind(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R; +// bind(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R; +// bind(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R; +// bind(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R; +// bind(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R; +function addFunc(a: number, b: number, c: number, d: number, e: number, f: number) { + return a + b + c + d + e + f; +} + +// 이건 bind(this: T, thisArg: ThisParameterType): OmitThisParameter; 가 적용됨 +const addFunc1 = addFunc.bind(null); +addFunc1(1, 2, 3, 4, 5, 6); + +// bind(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R; +// thisArg가 null, arg0이 1이다. +const addFunc2 = addFunc.bind(null, 1); +addFunc2(2, 3, 4, 5, 6); + +const addFunc3 = addFunc.bind(null, 1, 2); +addFunc3(3, 4, 5, 6); + +const addFunc4 = addFunc.bind(null, 1, 2, 3); +addFunc4(4, 5, 6); + +const addFunc5 = addFunc.bind(null, 1, 2, 3, 4); +addFunc5(5, 6); + +// 5개 이상일 때는 typescript의 bind 내부 타입으로 선언하지 않았다. +// 실제로 코딩하다보면 함수에서 이렇게 파라미터를 많이 만들지 않는다. 그래서 대부분 많이 존재하는 케이스까지만 만든 것 같다. +// 그래서 이 경우는 제일 마지막인 bind(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R; 가 적용된 것이다. +// 그리고 typescript 기술적 한계로 파라미터 개수에 따라 따로따로 만들지 않고 하나로 묶을 수 있는 방법이 없다는 문제도 있다...(앞으로 개선할 것이라고 기대중) +// 개선된 그 예로 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#variadic-tuple-types 에서 concat 타입을 한번 참고해보자. +const addFunc6 = addFunc.bind(null, 1, 2, 3, 4, 5); +addFunc6(6); diff --git a/09_ts/05_ts-all-in-one/20.ts b/09_ts/05_ts-all-in-one/20.ts new file mode 100644 index 0000000..a99c721 --- /dev/null +++ b/09_ts/05_ts-all-in-one/20.ts @@ -0,0 +1,34 @@ +// flat 타입 분석 +const originalArr1 = [1, 2, 3, [1, 2], [[1], [2]]].flat(); // [1, 2, 3, 1, 2, [1], [2]]; +const originalArr2 = [1, 2, 3, [1, 2]].flat(); // [1, 2, 3, 1, 2]; +const originalArr3 = [1, 2, 3, [1, 2], [[1], [2]]].flat(2); // [1, 2, 3, 1, 2, 1, 2]; + +type User = { + name: string, + age: number; +} +type UserType = User[1 extends number ? 'age' : 'name']; + +// 타입스크립트에서는 아래 처럼 값의 빼기 연산이 안된다. +// flat 타입 내부에서는 depth 하나 빼기 연산을 [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth] 와 같이 했다. +// 하지만 이것도 depth가 20 이상일 때는 커버가 불가능하지만 솔직히 그렇게 데이터 구조 짜는 것도 신기방기하긴 하다. +// type C = 3 - 1; + +// originalArr3 분석 +// FlatArray<(number[] | number[][] | number[][][]), 2>[] +// FlatArray<(number | number[] | number[][]), 1>[] +// FlatArray<(number | number[]), 0>[] -> 사실 정확히는 FlatArray<(number | number | number[]), 0>[] 인데 number | number 부분은 어차피 같은 number이다. +// FlatArray[] +// number[] + +// flat( +// this: A, +// depth?: D +// ): FlatArray[] + +// type FlatArray = { +// "done": Arr, +// "recur": Arr extends ReadonlyArray +// ? FlatArray +// : Arr +// }[Depth extends -1 ? "done" : "recur"]; \ No newline at end of file