return 타입 쓰지 않아도 알아서 유추함
function add(a:number,b:number){
return a+b;
}
const add: Add = (a:number, b:number) => a + b
Call(=Function) Signature를 통해 함수의 매개변수와 반환 값의 타입을 모두 type으로 미리 선언
type Add = {
(a: number, b: number): number;
}
// type Add = (a: number, b: number) => number;
const add: Add = (a, b) => a + b
//const add: Add = (a, b) => {a + b} : return이 void기 때문에 type error
: 직접 작성하기보다 외부 라이브러리에 자주 보이는 형태로, 하나의 함수가 복수의 Call Signature를 가질 때 발생한다
type Add = {
(a: number, b: number): number,
(a: number, b: string): number
}
const add: Add = (a, b) => {
if (typeof b === "string") return a;
return a + b;
}
매개변수의 데이터 타입이 다른 경우 예외 처리
type Add2 = {
(a: number, b: number): number,
(a: number, b: number, c: number): number
}
const add2: Add2 = (a, b, c?: number) => {//c는 옵션지만 쩄든 숫자임
//매개변수의 수가 다른 경우, 나머지 파라미터 c도 타입지정 필수
if (c) return a + b + c;
return a + b;
}
위와 같은 함수는 거의 없지만 외부 라이브러리에서 활용될 수 있음.
아래 Next.js의 예시는 자주 쓰임.
router.push("/home");
router.push({
path: "/home",
state: 1
});
예를 들어, Next.js의 라우터 push가 대충 두 가지 방법으로 페이지를 이동한다고 할 때,
type Config = {
path: string,
state: number
}
type Push = {
(config: Config): void,
(config: string): void
}
const push: Push = (config) => {
if (typeof config === "string") console.log(config);
else console.log(config.path);
}
: number,string,void 등
type SuperPrint={
(arr:number[]):void
(arr:boolean[]):void
}
const superPrint:SuperPrint=(arr)=>{
arr.forEach(i=>console.log(i));
}
superPrint([1,4,2,3]);
superPrint([true,false]);
superPrint([1,2,true])//이 arguments에 대한 call signature은 없기 때문에 동작x
: 타입의 placeholder => 무슨 타입인지 불확실할 때 사용, TS가 유추가능
type SuperPrint={
<TypePlaceholder>(arr:TypePlaceholder[]):void//Generic은 <T>를 주로 사용함
//<T>(a:T[])=>void
}
...
superPrint([1,4,2,3]);//이 라인에서 인자들의 타입을 알게 됨
superPrint([true,false]);
superPrint([1,2,true])//(arr:(number|boolean)[]):void 타입을 가짐
type SuperPrint={
<TypePlaceholder>(arr:TypePlaceholder[]):TypePlaceholder
//맨앞에 <T> 선언 필수
}
const superPrint:SuperPrint=(arr)=>arr[0]
const num1=superPrint([1,2,3])//num1의 타입은 number
const num2=superPrint([1,true,"d"])//num2의 타입은 number
//const superPrint: <string | number | boolean>(arr: (string | number | boolean)[]) => string | number | boolean
any와의 차이점
generic은 해당 타입에 대한 정보를 잃지 않는다.
any는 any로서 밖에 알 수 없지만 generics는 타입 정보를 알 수 있다.
const SuperPrint=<T,M>(a:T[],b:M)=>T
function superPrint<T>(a:T[]){
return a[0];
}
type Player<T> = {
name: string,
extraInfo: T
};
type NicoExtra = {age: number};
type NicoPlayer = Player<NicoExtra>;
const player: NicoPlayer = {
name: "joseph",
extraInfo: {
age: 23
}
};
const player2: Player<null> = {
name: "Yee",
extraInfo: null
};