function add(a: number, b:number){
return a+b;
}
- 보통 함수 매개변수의 타입은 명시적으로 정의한다.
- 특별한 상황을 제외하면 매개변수의 타입은 추론하지 않는다.
- 반환타입은 자동으로 추론하지만 원하면 명시할 수 있다.
- 실무에서는 반환타입을 추론하도록 하는 것이 보통이다.
- 타입스크립트에서 함수를 호출할 때 타입 정보는 따로 제공할 필요가 없다.
- 선택적 매개변수와 기본 매개변수
- ?를 이용해 선택적 매개변수를 지정할 수 있다.
- 실무에서는 선택적 매개변수보다 기본 매개변수를 자주 사요안다.
- 나머지 매개변수
- 인수를 여러개 받는 함수라면 목록을 배열 형태로 건넬 수도 있다.
- argument는 any타입으로 추론되기 떄문에 안전한 타입의 가변 인수 함수를 만드려면 나머지 매개변수를 이용해야한다.
- call, apply, bind
-
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으로 평가
- this의 타입
- 함수에서 this를 사용할 때에는 this타입을 함수의 첫번째 매개변수로 선언하자.
- 제너레이터 함수
- IterableIterator<제네릭> 으로 방출하는 타입을 감싸 제너레이터의 타입을 명시할 수 있다.
- 호출 시그니처
- 함수는 기본적으로 Function타입을 가지고 있다.
- 하지만 인수와 반환값에 대해서 호출 시그니처로 표현할 수 있다 (a: number, b: number) => number
- 함수에서 함수로 인수를 전다랗거나 함수에서 다른 함수를 반환하는 경우 이 문법으로 인수나 반환 함수의 타입을 지정할 수 있다.
- 함수 호출 시그니처는 값이아닌 타입 정보만 포함한다.
- 문맥적 타입화
-
function times(
f: (index: number) => void,
n: number
){
for(let i = 0 ; i < n ; i++){
f(i);
}
}
- times를 호출할 때 함수 선언을 인라인으로 제공하면 인수로 전달하는 함수의 타입을 명시할 필요가 없다 (times(n => console.log(n), 4);
- times의 시그니처에서 f의 인수 index를 number로 선언했으므로 타입스크립트는 문맥상 n이 number임을 추론할 수 있다.
- 인라인으로 제공하면 추론이 불가능하다
- 오버로드된 함수 타입
- type Fn = (...) => ... 는 단축형 호출 시그니처이다.
- type Log = (message: string, userId?: string) => void
- type Log ={ (message: string, userId?: string) : void } //위와 아래의 기능은 같다.
- 타입스크립트는 동적 특징을 오버로드된 함수 선언으로 제공하고 입력 타입에 따라 달라지는 함수의 출력타입은 정적 시스템으로 각각 제공한다.
- <a> 요소는 HTMLAnchorElement
- <canvas>는 HTMLCanvasElement
- <table>는 HTMLTableElement
- 오버로드된 호출 시그니처는 createElement의 동작을 구현하기에 이상적인 메커니즘이다
-
type CreateElement = {
(tag: 'a') = HTMLAnchorElement
(tag: 'canvas'): HTMLCanvasElement
(tag: 'table'): HTMLTableElement
(tag: 'string'): HTMLElement
}
let createElement: CreateElement = (tag: string): HTMLElement =>{
//...
}
- 다형성
- 구체타입이란? (boolean, string, Date[], {a:number} | {b:string}, (numbers: number[]) => number)
- 기대하는 타입을 정확하게 알고 있고 실제로 이 타입이 전달되었는지 확인 할 때 유용하다.
-
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[]
}
- 제네릭 타입 매개변수
- 여러장소에 타입 수준의 제한을 적용할 때 사용하는 플레이스 홀더 타입.
- 다형성 타입 매개변수라고도 한다.
- type Filter = { <T>(array: T[]}, f:(item: T) =>boolean): T[] }
- T타입이 무엇인지 지금은 알 수 없으니 filter호출시마다 타입스크립트가 타입을 추론하도록 한다. 타입을 추론해낸 뒤 정의된 모든 T를 추론한 타입으로 대체한다.
- 함수의 매개변수가 함수를 호출 할 때 건네진 인수로 매번 다시 한정되듯, T도 filter를 호출할 때마다 새로운 타입으로 한정된다.
-
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)
- 제네릭 T도 T가 한정하는 타입이 무엇이든 모든 T를 같은 타입으로 제한한다.
- 언제 제네릭 타입이 한정되는가?
- 제네릭타입의 선언 위치에 따라 타입의 범위 뿐 아니라 타입스크립트가 제네릭타입을 언제 구체 타입으로 한정하는지 결정된다.
- 제네릭을 어디에 선언할 수 있을까?
- 호출 시그니처를 정의하는 방법에 따라 제네릭을 추가하는 방법이 정해져있다.
-
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[]{
// ...
}
- 제네릭 타입 추론
- 제네릭도 명시적으로 지정할 수 있다.
-