function greeter(fn: (a: string) => void) {
fn("Hello, World");
}
(a: string) => void
: 문자열 타입인 a 매개변수를 가지고 있고, 반환값이 없는 함수 타입
function type expression에서 매개변수 이름이 꼭 들어가야 함
(string) => void
로 작성할 경우, any 타입인 string 매개변수를 가지고 있고 반환타입이 없는 타입이 됨type alias를 사용하여 함수 타입에 이름을 지어줄 수 있음
type GreetFunction = (a: string) => void;
function greeter(fn: GreetFunction) {
// ...
}
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
console.log(fn.description + " returned " + fn(6));
}
function fn(n: number) {
return n + 1 > 6;
}
fn.description = 'black';
doSomething(fn); // 'black returned true'
()=>
대신 :
를 사용함type Function = {
(x: number, y: number): number;
(x: number): boolean;
};
new
키워드를 붙여서 작성함type SomeConstructor = {
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
return new ctor("hello");
}
Date
와 같은 객체는 new
키워드와 같이 또는 없이 호출될 수 있음interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
function createClock(
ctor: ClockConstructor,
hour: number,
minute: number
): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
construct signature - stackoverflow
generic
을 사용함Type
을 선언하여 작성됨Type
를 추가함으로써 함수의 매개변수와 반환값 사이의 연결을 만듬function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
// s is of type 'string'
const s = firstElement(["a", "b", "c"]);
// n is of type 'number'
const n = firstElement([1, 2, 3]);
// u is of type undefined
const u = firstElement([]);
Type
은 추론되므로 구체화하지 않아도 됨Type
을 사용해도 됨function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
return arr.map(func);
}
// Parameter 'n' is of type 'string'
// 'parsed' is of type 'number[]'
const parsed = map(["1", "2", "3"], (n) => parseInt(n));
constraint
를 사용하여 타입 매개변수로 받아들일 수 있는 타입 종류를 제한할 수 있음constraint
는 extends
절로 작성됨function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
// longerArray is of type 'number[]'
const longerArray = longest([1, 2], [1, 2, 3]);
// longerString is of type 'alice' | 'bob'
const longerString = longest("alice", "bob");
// Error! Numbers don't have a 'length' property
const notOK = longest(10, 100);
Type
을 { length: number }
로 제한했기 때문에 .length
속성에 접근할 수 있었음function minimumLength<Type extends { length: number }>(
obj: Type,
minimum: number
): Type {
if (obj.length >= minimum) {
return obj;
} else {
return { length: minimum }; // Error
/*
Type '{ length: number; }' is not assignable to type 'Type'.
'{ length: number; }' is assignable to the constraint of type 'Type',
but 'Type' could be instantiated with a different subtype of constraint '{ length: number; }'.
*/
}
}
// 'arr' gets value { length: 6 }
const arr = minimumLength([1, 2, 3], 6);
// and crashes here because arrays have a 'slice' method,
// but not the returned object!
console.log(arr.slice(0));
Type
이나 constraint와 일치하는 값을 반환함function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
const arr = combine([1, 2, 3], ["hello"]); // Error : Type 'string' is not assignable to type 'number'.
const arr = combine<string | number>([1, 2, 3], ["hello"]); // OK
- constraint을 사용하기보다는 타입 매개변수 그 자체를 사용하기
function firstElement1<Type>(arr: Type[]) {
return arr[0];
}
function firstElement2<Type extends any[]>(arr: Type) {
return arr[0];
}
// a: number (good)
const a = firstElement1([1, 2, 3]);
// b: any (bad)
const b = firstElement2([1, 2, 3]);
Type
인 반면에 firstElement2의 반환 타입은 constraint에 의해 any
임
- 가능하면 적은 타입 매개변수를 사용하기
function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
return arr.filter(func);
}
function filter2<Type, Func extends (arg: Type) => boolean>(
arr: Type[],
func: Func
): Type[] {
return arr.filter(func);
}
Func
는 함수에 들어오는 타입 매개변수와 반환값과 관련이 없으므로 타입 매개변수로 선언하지 않아도 됨
- 타입 매개변수는 여러 값의 타입이 연관 있을 때만 사용하기
// bad
function greet<Str extends string>(s: Str) {
console.log("Hello, " + s);
}
// good
function greet(s: string) {
console.log("Hello, " + s);
}
?
키워드를 붙인 매개변수는 선택적으로 받을 수 있음function f(x?: number) {
// ...
}
f(); // OK
f(10); // OK
undefined
가 전달됨function myForEach(arr: any[], callback: (arg: any, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i]);
}
}
myForEach([1, 2, 3], (a, i) => {
console.log(i.toFixed()); // Error : Object is possibly 'undefined'.
});