function greeter(fn: (a: string) => void) {
fn("Hello, World");
}
function printToConsole(s: string) {
console.log(s);
}
// any => void
function printToConsole(string) {
console.log(string);
}
// 타입 별칭 사용도 가능
type GreetFunction = (a: string) => void;
function greeter(fn: GreetFunction) {
// ...
}
greeter(printToConsole);
type DescribableFunction = {
description: string;
(someArg: number): boolean;
};
// 문법이 앞선 경우와 다름
function doSomething(fn: DescribableFunction): void {
console.log(fn.description + " returned " + fn(6));
}
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;
}
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const s = firstElement(["a", "b", "c"]); //string
const n = firstElement([1, 2, 3]); //number
const u = firstElement([]);//undefined
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
const longerArray = longest([1, 2], [1, 2, 3]);
const longerString = longest("alice", "bob");
// Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
const notOK = longest(10, 100);
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
//Type 'string' is not assignable to type 'number'.
const arr = combine([1, 2, 3], ["hello"]);
//OK
const arr = combine<string | number>([1, 2, 3], ["hello"]);
// good
function firstElement1<Type>(arr: Type[]) {
return arr[0];
}
// bad, 호출 시점에 extends any[]를 보고 타입을 any로 추론함
function firstElement2<Type extends any[]>(arr: Type) {
return arr[0];
}
// good
function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
return arr.filter(func);
}
// bad, 무의미한 Func 타입 사용
function filter2<Type, Func extends (arg: Type) => boolean>(
arr: Type[],
func: Func
): Type[] {
return arr.filter(func);
}
// good
function greet(s: string) {
console.log("Hello, " + s);
}
// bad, 제네릭이 필요없는 함수
function greet<Str extends string>(s: Str) {
console.log("Hello, " + s);
}
// name: string | undefined
function printHello(name?: string) {
console.log(`hello! ${name ?? ""}`)
}
// name: string
function printHello(name = "Typescript") {
console.log(`hello! ${name}`)
}
printHello(); //"hello! Typescript"
function myForEach(arr: any[], callback: (arg: any, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i);
}
}
// 자바스크립트에서 매개변수보다 많은 인수를 전달하면 남은 인수들은 무시됨
// 타입스크립트는 함수가 다음과 같이 구현될 가능성이 있다 판단
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()); // Object is possibly 'undefined'.
});
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
const d1 = makeDate(12345678); //ok
const d2 = makeDate(5, 5, 5); //ok
const d3 = makeDate(1, 3); // No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
function fn(x: string): void;
function fn(): void; // 매개변수 없이 함수를 호출하려면 구현 시그니처 이외에 오버로드 시그니처 명시 필요
function fn() {
// ...
}
fn(); //Expected 1 arguments, but got 0.
function fn1(x: boolean): void;
function fn1(x: string): void;
function fn2(x: string): string;
function fn2(x: number): boolean;
// This overload signature is not compatible with its implementation signature.
function fn1(x: boolean) {} // x: boolen | string
function fn2(x: string | number) {
return "oops"; // string => string, number => boolean 식으로 수정 필요
}
function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
return x.length;
}
len(""); // OK
len([0]); // OK
len(Math.random() > 0.5 ? "hello" : [0]); // 타입을 number[] | "hello"(string) 로 인식
// 유니언 타입을 사용하면 더 깔끔한 코드로 문제 해결 가능
function len(x: any[] | string) {
return x.length;
}
const user = {
id: 123,
admin: false,
becomeAdmin: function () {
this.admin = true; //this -> user에 들어오는 객체
},
};
interface DB {
filterUsers(filter: (this: User) => boolean): User[];
}
const db = getDB();
const admins = db.filterUsers(function (this: User) {
return this.admin;
});
const admins = db.filterUsers(() => this.admin); // 화살표 함수에서는 this 할당 불가능
any
가 아닌 any[]
가 되며, 타입 표현식은 Array<T>
, T[]
, 튜플 타입으로 표현해야 함function multiply(n: number, ...m: number[]) {
return m.map((x) => n * x);
}
const a = multiply(10, 1, 2, 3, 4); //[10, 20, 30, 40]
const args = [8, 5]; //number[]
// A spread argument must either have a tuple type or be passed to a rest parameter.
const angle = Math.atan2(...args);
const args = [8, 5] as const; // 길이가 2인 튜플
const angle = Math.atan2(...args); //ok
// 1. 각각의 인자의 타입을 지정
function sum({ a, b, c }: { a: number; b: number; c: number }) {
console.log(a + b + c);
}
// 2. 타입을 따로 지정해 사용
type ABC = { a: number; b: number; c: number };
function sum({ a, b, c }: ABC) {
console.log(a + b + c);
}
type voidFunc = () => void;
const f1: voidFunc = () => {
return true;
};
const f2: voidFunc = () => true;
const f3: voidFunc = function () {
return true;
};
// 전부 true 출력
console.log(f1());
console.log(f2());
console.log(f3());
출처:
https://www.typescriptlang.org/ko/docs/handbook/2/functions.html