TypeScript
[TypeScript] Functions
winter17
2023. 8. 3. 12:20
◆ Functions
▷ 숫자 타입의 함수
function add(num1:number, num2:number):number{
return num1 + num2
}
add(1, 2)
▷ 불리언 타입의 함수
function isAdult(age:number):boolean{
return age > 19
}
isAdult(17)
▷ 매개변수가 선택인 경우
function hello(name?:string){
// name이 있으면 name을 쓰고, 아니라면 'world'
return `Hello, ${name || 'world'}`
}
▷ 매개변수에 기본값 지정
function hello2(name = 'world'){
return `Hello, ${name}`
}
▷ 필수 매개변수가 먼저
function hello3(name:string, age?:number):string{
if(age !== undefined){
return `Hello, ${name}, You are ${age}.`
}else{
return `Hello, ${name}`
}
}
▷ ...nums는 함수 호출 시 전달되는 인수들을 배열로 묶어서 저장하는 역할
// ...nums는 함수 호출 시 전달되는 인수들을 배열로 묶어서 저장하는 역할
function sum(...nums:number[]){
return nums.reduce((acc, cur) => acc + cur, 0)
}
▷ this, bind, interface
interface User{
name:string
}
// Sam객체는 User타입을 가진다
const Sam: User = {name:'Sam'}
//
function showName(this:User){
// this의 타입을 지정할 때는 가장 첫 번째 매개변수로!
console.log(this.name)
}
// bind를 사용하여 Sam객체를 showName함수와 바인딩하여 새로운 함수 a를 생성
// bind메서드는 Sam객체를 showName함수의 this로 지정한다
const a = showName.bind(Sam)
a()
// a를 호출하면 showName함수 내부의 console.log(this.name)에서 this는 Sam객체를 가리킨다
// 따라서 a() 함수를 호출하면 Sam객체의 name인 Sam이 출력된다
▷ call signatures
- 객체가 함수처럼 호출될 수 있는 타입을 정의하는 것을 말한다
- 함수의 시그니처와 비슷한 개념으로, 함수를 호출할 때 사용되는 매개변수의 타입과 반환 타입을 명시적으로 지정하는 것
- 콜 시그니처는 주로 인터페이스나 타입 별칭 내에서 정의된다
// Add: 콜 시그니처를 나타내는 타입 별칭의 이름
type Add = (a: number, b: number) => number
const add: Add = (a, b) => a + b
▷ Overload
- 직접 오버로딩을 작성하기보다 어떻게 사용되는지에 집중할 것!
- 함수가 여러개의 call signatures를 가지고 있을 때 발생시킴
- 하나의 함수 이름으로 다양한 타입의 인수를 받아 다양한 방식으로 처리하는 것
// Config / Push: Call Signature
type Config = {
path: string,
state: object
}
type Push = {
(path: string):void
(config: Config): void
}
const push:Push = (config) => {
if (typeof config === 'string') { console.log(config) }
else {
console.log(config.path, config.state)
}
}
// 다른 call signatures에 파라미터 개수도 다른 경우
type Add = {
(a: number, b: number): number
// 마지막 파라미터 c는 옵션
(a: number, b: number, c:number): number,
}
const add:Add = (a, b, c?:number) => {
if (c) return a + b + c
return a + b
}
add(1, 2)
add(1, 2, 3)
interface User{
name: string
age: number
}
// 오버로드
// join함수는 두 개의 오버로드 시그니처를 가지고 있다
// name, age가 모두 문자열 타입인 경우 -> 이 경우 함수는 문자열 타입 값을 반환
function join(name: string, age: string): string;
// name은 문자열, age는 숫자인 경우 -> 이 함수는 User 인터페이스를 따르는 객체를 반환
function join(name: string, age: number): User;
// name은 항상 문자열이어야하고, age는 숫자나 문자열 중 하나의 타입을 가질 수 있다.
// 만약 age가 숫자 타입이라면 User 인터페이스를 따르는 객체를 반환하고
// 문자열 타입이라면 나이는 숫자로 입력해달라는 문자열을 반환한다.
function join(name: string, age: number|string):User | string{
if(typeof age === 'number'){
return{
name,
age,
}
}else{
return '나이는 숫자로 입력해주세요'
}
}
const jane: string = join('Jane', '30') // 첫 번째 시그니처 선택
const sam: User = join('Sam', 30) // 두 번째 시그니처 선택
▷ ploymorphism(다형성)
- 하나의 인터페이스나 기능을 여러 개체(클래스)가 다양한 방식으로 구현하는 능력
- 코드의 재사용성과 유연성을 높여주며 객체 지향 프로그래밍의 핵심 원칙 중 하나인 '인터페이스에 의존, 구현에 의존하지 않기'를 구현하는데 도움이 된다
- poly: many, morphos: structure → 여러가지 다른 구조/모양
- 컴파일 시 다형성(Compile-time Polymorphism)
- 메서드 오버로딩(Method Overloading): 동일한 메서드 이름을 가지고 매개변수의 개수나 타입이 다른 여러 메서드를 정의하는 것, 컴파일러는 오버로딩된 메서드를 호출하는 코드를 컴파일 시점에서 정확히 파악하여 적절한 메서드를 선택한다
- 연산자 오버로딩(Operator Overloading): 기존에 정의된 연산자를 새로운 클래스 타입에 맞게 재정의하여 사용하는 것을 말한다
- 런타임 시 다형성(Runtime Polymorphism)
- 메서드 오버라이딩(Mothod Overrding): 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 동일한 시그니처로 재정의하는 것이다. 런타임 시점에서 객체의 실제 타입에 따라 적절한 메서드가 호출된다. 이는 객체 지향 프로그래밍의 상속 개념과 밀접한 관련이 있다
- 인터페이스(interface): 다형성을 활용하기 위한 중요한 도구로 인터페이스는 클래스가 구현해야 할 메서드들의 집합을 정의한다. 클래스는 인터페이스를 구현함으로써 인터페이스에 정의된 메서드들을 재정의하고, 이를 통해 객체의 다형성을 구현할 수 있다.
▷ Generic
- 제네릭은 타입의 placeholder 같은 존재, 자동으로 타입을 추론
- 제네릭은 클래스나 함수를 정의할 때, 타입을 파라미터로 사용하여 여러 종류의 타입에 대해 동작하도록 설계하는 방법이다.
- 제네릭은 선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있도록 하는 기법
- 프로그래밍 언어에서 타입을 일반화하여 코드의 재사용성과 유연성을 높이는 기능을 말한다
- 타입에 독립적으로 작동하는 코드를 작성할 수 있게 해 준다 → 재사용, 유지 보수성을 높임
- concrete type: number, string, boolean, void 등
// Call Signature 타입 정의
// Generic 타입 매개변수 T를 사용하여 함수의 입력 배열과 반환 타입을 유연하게 정의할 수 있도록 한다
type SuperPrint = <T>(a: T[]):T
// 함수 구현
const superPrint: SuperPrint = (a) => a[0]
// 변수 선언 -> 결과 타입 및 설명
const a = superPrint([1, 2, 3, 4]) // 1
const b = superPrint([true, false, true]) // true
const c = superPrint(['a', 'b', 'c']) // 'a'
const d = superPrint([1, 2, true, false]) // 1
// 위에서 제네릭으로 타입을 설정한 것과 같다
function superPrint<T>(a: T[]){
return a[0]
}
// Player는 E라는 제네릭을 가지고 있다
type Player<E> = {
name: string
extraInfo: E
}
type NicoExtra = {
favFood: string
}
type NicoPlayer = Player<NicoExtra>
const nico: NicoPlayer = {
name: 'nico',
extraIfo: {
favFood: 'kimchi'
}
}
const lynn: Player<null> = {
name: 'lynn',
extraInfo: null
}
2023.08.03 - [TypeScript] - [TypeScript] 함수 연습 문제 function, call signatures, generic