개발노트

3. [TypeScript] Call Signatures, Overloading, Polymorphism 개념 정리 본문

웹 개발/TypeScript

3. [TypeScript] Call Signatures, Overloading, Polymorphism 개념 정리

mroh1226 2023. 7. 31. 18:31
반응형

Call Signatures

  • Call Signatures는 TypeScript에서 함수 타입을 정의하는데 사용되는 방법 중 하나입니다. 
  • 함수는 객체와 마찬가지로 일급 객체로서, 변수에 할당하거나 매개변수로 전달할 수 있습니다. 
  • 따라서 TypeScript에서 함수의 타입을 명시적으로 정의하고 사용하고자 할 때 Call Signatures를 활용합니다
  • 함수의 매개변수와 반환 타입을 명시하며, 함수의 매개변수와 반환 타입 사이에 => 기호를 사용하여 표현합니다.
type NumFunc = (a:number,b:number)=> number;
const add:NumFunc = (a,b) => a+b
const sub:NumFunc = (a,b) => a-b
const divide:NumFunc = (a,b) => a/b
const multiply:NumFunc = (a,b) => a*b

console.log(add(10,20));
console.log(sub(10,20));
console.log(divide(10,20));
console.log(multiply(10,20));

콘솔 결과값.


Overloading

오버라이딩(Overriding)은 객체 지향 프로그래밍에서 다형성(Polymorphism)을 구현하는 방법 중 하나입니다. 오버라이딩은 부모 클래스(또는 상위 클래스)에 정의된 메서드를 자식 클래스(또는 하위 클래스)에서 동일한 이름으로 다시 정의하여 자식 클래스의 특정 동작을 변경하거나 확장하는 것을 말합니다.

예시1.

// 숫자를 두 개 받아 덧셈한 결과를 반환하는 오버로딩된 함수
function add(a: number, b: number): number;
// 문자열을 두 개 받아 합쳐서 반환하는 오버로딩된 함수
function add(a: string, b: string): string;

// 오버로딩된 함수 구현
function add(a: number | string, b: number | string): number | string {
  if (typeof a === "number" && typeof b === "number") {
    return a + b;
  } else if (typeof a === "string" && typeof b === "string") {
    return a + b;
  } else {
    throw new Error("Invalid arguments");
  }
}

// 오버로딩된 함수 호출
console.log(add(10, 20)); // Output: 30
console.log(add("Hello", " TypeScript")); // Output: Hello TypeScript

 

예시2.

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);
  }
}

Polymorphism

  • TypeScript에서 Polymorphism(다형성)은 객체 지향 프로그래밍의 중요한 개념 중 하나로, 하나의 인터페이스나 클래스가 다양한 타입을 가질 수 있고, 동일한 인터페이스나 클래스를 기반으로 서로 다른 구현을 할 수 있는 능력을 말합니다. 다형성은 코드의 재사용성과 유연성을 높여주며, 객체 지향 프로그래밍의 핵심 원칙 중 하나인 "객체 지향 설계의 개방/폐쇄 원칙(OCP)"을 지원합니다.

    TypeScript에서 다형성을 구현하는 방법은 크게 두 가지입니다:
    • 상속(Inheritance)을 통한 다형성:
      상속을 이용하여 부모 클래스의 메서드를 자식 클래스에서 재정의(오버라이딩)하여 다양한 동작을 구현하는 것이 가능합니다. 자식 클래스들은 모두 부모 클래스의 타입을 가지므로, 부모 클래스의 타입으로 자식 클래스의 객체를 참조하고 사용할 수 있습니다. 이렇게 상속 관계에 있는 클래스들은 동일한 인터페이스를 공유하면서 다양한 구현을 제공할 수 있습니다.

    • 인터페이스(Interfaces)를 통한 다형성:
      TypeScript에서 인터페이스를 사용하면 다양한 객체들이 동일한 인터페이스를 구현할 수 있습니다. 인터페이스는 특정한 속성과 메서드의 집합으로 객체가 해당 인터페이스를 구현하면, 인터페이스에 정의된 동작을 보장합니다. 따라서 인터페이스를 사용하여 다양한 객체들을 통일된 방법으로 사용할 수 있고, 더 많은 유연성을 제공합니다.
  • 다형성의 장점은 다음과 같습니다
    • 유연성: 다양한 타입들을 통일된 방법으로 사용할 수 있어서 코드의 재사용성과 유지보수성이 향상됩니다.
    • 확장성: 새로운 클래스나 타입을 추가하여 기존의 코드를 수정하지 않고도 다양한 동작을 추가할 수 있습니다.
    • 가독성: 다형성을 이용하면 코드가 간결하고 읽기 쉽게 구성될 수 있습니다.
    • 타입 안정성: TypeScript에서 다형성을 적절하게 활용하면 타입 체크를 통해 런타임 에러를 방지하고 안정적인 코드를 작성할 수 있습니다.
  • any를 사용하면 밖에서 타입정보를 알 수 었기 때문에 타입 정보를 알 수 있는 Generics를 사용합니다.
type SuperPrint = {
  (arr: number[]):void
  (arr: boolean[]):void
  (arr: string[]):void
  (arr: (number|boolean|string)[]):void
}
const superPrint:SuperPrint =(arr) =>{
  arr.forEach(i => console.log(i));
}
superPrint([1,2,3,4]);
superPrint([true,true,false,false]);
superPrint(['A','B','C','D']);
superPrint([1,'A',true]);

//Generic 사용 시
type SuperPrint2 = {
  <TypePlaceholder>(arr: TypePlaceholder[]):void
}
const superPrint2:SuperPrint2 =(arr) =>{
  arr.forEach(i => console.log(i));
}
superPrint2([1,2,3,4]);
superPrint2([true,true,false,false]);
superPrint2(['A','B','C','D']);
superPrint2([1,'A',true]);

 

// 다형성을 위한 call signature 예시
type TransformFunction<T, M> = (data: T) => M;

// 숫자를 문자열로 변환하는 함수
const numberToString: TransformFunction<number, string> = (num) => num.toString();

// 문자열을 숫자로 변환하는 함수
const stringToNumber: TransformFunction<string, number> = (str) => parseInt(str, 10);

// 배열의 요소들을 문자열로 변환하는 함수
const arrayToString: TransformFunction<number[], string> = (arr) => arr.join(", ");

// 다른 타입으로 변환하는 함수를 호출해보기
console.log(numberToString(42)); // Output: "42"
console.log(stringToNumber("123")); // Output: 123
console.log(arrayToString([1, 2, 3])); // Output: "1, 2, 3"
// 다형성을 위한 제네릭 함수 예시
function transform<T, M>(data: T): M {
  return data as unknown as M;
}

const numToBool: boolean = transform<number, boolean>(42);
const strToNum: number = transform<string, number>("123");
const arrToObj: { key: number } = transform<number[], { key: number }>([1, 2, 3]);

console.log(numToBool); // Output: true
console.log(strToNum); // Output: 123
console.log(arrToObj); // Output: { key: 1 }
반응형
Comments