TS/[책] 타입스크립트 프로그래밍

4장. 함수 [not fin]

배워도끝이없네 2021. 11. 27. 22:02
function add(a: number, b:number){
	return a+b;
}
  • 보통 함수 매개변수의 타입은 명시적으로 정의한다.
  • 특별한 상황을 제외하면 매개변수의 타입은 추론하지 않는다.
  • 반환타입은 자동으로 추론하지만 원하면 명시할 수 있다.
  • 실무에서는 반환타입을 추론하도록 하는 것이 보통이다.
  • 타입스크립트에서 함수를 호출할 때 타입 정보는 따로 제공할 필요가 없다.
  1. 선택적 매개변수와 기본 매개변수
    1. ?를 이용해 선택적 매개변수를 지정할 수 있다.
    2. 실무에서는 선택적 매개변수보다 기본 매개변수를 자주 사요안다.
  2. 나머지 매개변수
    1. 인수를 여러개 받는 함수라면 목록을 배열 형태로 건넬 수도 있다.
    2. argument는 any타입으로 추론되기 떄문에 안전한 타입의 가변 인수 함수를 만드려면 나머지 매개변수를 이용해야한다.
  3. call, apply, bind
    1.  
    2. function add(a: number, b: number): number { return a+b; } add(10,20) //30으로 평가 add.apply(null,[10,20]) //30으로 평가 add.call(null, 10, 20) //30으로 평가 add.bind(null, 10, 20)() //30으로 평가
  4. this의 타입
    1. 함수에서 this를 사용할 때에는 this타입을 함수의 첫번째 매개변수로 선언하자.
  5. 제너레이터 함수
    1. IterableIterator<제네릭> 으로 방출하는 타입을 감싸 제너레이터의 타입을 명시할 수 있다.
  6. 호출 시그니처
    1. 함수는 기본적으로 Function타입을 가지고 있다.
    2. 하지만 인수와 반환값에 대해서 호출 시그니처로 표현할 수 있다 (a: number, b: number) => number
    3. 함수에서 함수로 인수를 전다랗거나 함수에서 다른 함수를 반환하는 경우 이 문법으로 인수나 반환 함수의 타입을 지정할 수 있다.
    4. 함수 호출 시그니처는 값이아닌 타입 정보만 포함한다.
  7. 문맥적 타입화
    1. function times(
      	f: (index: number) => void,
          n: number
      ){
      	for(let i = 0 ; i < n ; i++){
          	f(i);
          }
      }
    2. times를 호출할 때 함수 선언을 인라인으로 제공하면 인수로 전달하는 함수의 타입을 명시할 필요가 없다 (times(n => console.log(n), 4);
    3. times의 시그니처에서  f의 인수 index를 number로 선언했으므로 타입스크립트는 문맥상 n이 number임을 추론할 수 있다.
    4. 인라인으로 제공하면 추론이 불가능하다
  8. 오버로드된 함수 타입
    1. type Fn = (...) => ... 는 단축형 호출 시그니처이다.
    2. type Log = (message: string, userId?: string) => void
    3. type Log ={ (message: string, userId?: string) : void } //위와 아래의 기능은 같다.
    4. 타입스크립트는 동적 특징을 오버로드된 함수 선언으로 제공하고 입력 타입에 따라 달라지는 함수의  출력타입은 정적 시스템으로 각각 제공한다. 
    5. <a> 요소는 HTMLAnchorElement
    6. <canvas>는 HTMLCanvasElement
    7. <table>는 HTMLTableElement
    8. 오버로드된 호출 시그니처는 createElement의 동작을 구현하기에 이상적인 메커니즘이다
    9. type CreateElement = {
      	(tag: 'a') = HTMLAnchorElement
          (tag: 'canvas'): HTMLCanvasElement
          (tag: 'table'): HTMLTableElement
          (tag: 'string'): HTMLElement
      }
      
      let createElement: CreateElement = (tag: string): HTMLElement =>{
       //...
      }

 

  • 다형성
    1. 구체타입이란? (boolean, string, Date[], {a:number} | {b:string}, (numbers: number[]) => number) 
    2. 기대하는 타입을 정확하게 알고 있고  실제로 이 타입이 전달되었는지 확인 할 때 유용하다.
    3. function filter(array, f) {
      	let result = [];
          for (let i = 0; i < array.length; i++){
          	let item = array[i];
              if(f(item)){
              	result.push(item)
              }
          }
          return result;
      }
      
      filter([1,2,3,4], _=> _<3) //[1,2]로 평가
      
      type Filter = { //filter의 전체 타입 시그니처
      	(array:unknown, f: unknown) => unknonwn[]
      }
      
      type Filter = { // number 타입이라고 가정해 unknown을 number로 변환
      	(array: number[], f: (item: number) => boolean): number[]
      }
    4. 제네릭 타입 매개변수
      1. 여러장소에 타입 수준의 제한을 적용할 때 사용하는 플레이스 홀더 타입. 
      2. 다형성 타입 매개변수라고도 한다.
      3. type Filter = { <T>(array: T[]}, f:(item: T) =>boolean): T[] }
      4. T타입이 무엇인지 지금은 알 수 없으니 filter호출시마다 타입스크립트가 타입을 추론하도록 한다. 타입을 추론해낸 뒤 정의된 모든 T를 추론한 타입으로 대체한다.
      5. 함수의 매개변수가 함수를 호출 할 때 건네진 인수로 매번 다시 한정되듯, T도 filter를 호출할 때마다 새로운 타입으로 한정된다.
      6. type Filter = {
        	<T>(array: T[], f: (item: T) => boolean): T[]
        }
        
        let filter: Filter = (array, f) => // ...
        
        //T는 number로 한정됨
        filter(1,2,3], _=> _>2)
        
        //T는 string으로 한정됨
        filter('a','b'], _=> _!==2)
         
      7. 제네릭 T도  T가 한정하는 타입이 무엇이든 모든 T를 같은 타입으로 제한한다.
        1. 언제 제네릭 타입이 한정되는가?
          1. 제네릭타입의 선언 위치에 따라 타입의 범위 뿐 아니라 타입스크립트가 제네릭타입을 언제 구체 타입으로 한정하는지 결정된다.
        2. 제네릭을 어디에 선언할 수 있을까?
          1. 호출 시그니처를 정의하는 방법에 따라 제네릭을 추가하는 방법이 정해져있다.
          2. type Filter ={
            	<T>(array: T[], f: (item:T) => boolean): T[]
            }
            let filter: Filter = // ...
            
            type Filter<T> = {
            	(array: T[], f: (itme: T) => boolean): T[]
            }
            let filter: Filter<number> = //...
            
            type Filter = <T>(array: T[], f: (item: T) => boolean) =>T[]
            let filter: Filter = // ...
            
            type Filter<T> = (array: T[], f: (item: T)=> boolean) => T[]
            let filter: Filter<string> = //...
            
            function filter<T>(array: T[], f:(item: T) => boolean): T[]{
            	// ...
            }
        3. 제네릭 타입 추론
          1. 제네릭도 명시적으로 지정할 수 있다.
          2.