타입스크립트(TS) 함수 정리

·2024년 11월 13일

TS

목록 보기
4/5

타입스크립트 함수 정리

함수시그니처 작성방법

const printMe = (name: string, age: number): void => {
  console.log(name, age);
};

위와같은 경우에 인자값이 늘어날 경우 엄청나게 타입선언이 길어짐

타입별칭

type PrintMeFnc = (name: string, age: number) => void;

const printMe: PrintMeFnc = (name, age) => {
  console.log(name, age);
};

const printMe: (arg01: string, arg02: number) => void = (name, age) => {
  console.log(name, age);
};

타입별칭

const printMe: (arg01: string, arg02: number) => void = (name, age) => {
  console.log(name, age);
};


type PrintMeFnc = (name: string, age: number) => void;

const printMe: PrintMeFnc = (name, age) => {
  console.log(name, age);
};

타입가드

  • 비동기로 데이터를 가져오는 경우 삼항연산자로 예외처리
interface Namealbe2 {
  name: string;
}

const getName = (o: Namealbe2): string => {
  return o != undefined ? o.name : "Loading";
};

const dataResult = getName(undefined);
console.log(dataResult);
console.log(getName({ name: "David" }));

콜백함수

콜백함수 타입정리

const calc = (value: number, cb: (arg: number) => void): void => {
  let add = (a: number, b: number) => a + b;
  let multiplay = (a: number, b: number) => a * b;

  let result = multiplay(add(1, 2), value);
  cb(result);
};

calc(30, (result: number) => console.log(`result is ${result}`));

콜백함수를 고차함수로 사용

const add =
  (a: number): ((arg: number) => number) =>
  (b: number) =>
    a + b;

const result = add(1)(2);
console.log(result);
type NumberToNumber = (arg0: number) => number; //함수의 시그니처

const add = (a: number): NumberToNumber => {
  const _add = (b: number): number => {
    return a + b;
  };

  return _add;
};

const result = add(1)(2);

console.log(result);

서로소 유니온 타입

  • 서로소 : 교집합이 없는 관계
type Admin = {
  name: string;
  kickCount: number;
};

type Member = {
  name: string;
  point: number;
};

type Guest = {
  name: string;
  visitCount: number;
};

type User = Admin | Member | Guest; // 유니온타입

const login = (user: User) => {
  if ("kickCount" in user) {
    console.log(`${user.name}는 관리자이며 ${user.kickCount}회 관리했습니다.`);
  } else if ("point" in user) {
    console.log(`${user.name}는 멤버이며 ${user.point}를 적립했습니다.`);
  } else if ("visitCount" in user) {
    console.log(`${user.name}는 손님이며 ${user.visitCount}번 방문했습니다.`);
  }
};

좀 더 직관적으로

const login = (user: User) => {
  switch (user.tag) {
    case "ADMIN": {
      console.log(
        `${user.name}는 관리자이며 ${user.kickCount}회 관리했습니다.`
      );
      break;
    }
    case "MEMBER": {
      console.log(`${user.name}는 멤버이며 ${user.point}를 적립했습니다.`);
      break;
    }
    case "GUEST": {
      console.log(`${user.name}는 손님이며 ${user.visitCount}번 방문했습니다.`);
      break;
    }
  }
};

실제 예시

type LoadingTask = {
  state: "Loading";
};

type FailedTask = {
  state: "FAILED";
  error: {
    message: "오류 발생...";
  };
};

type SuccessTask = {
  state: "SUCCESS";
  response: {
    data: "movie...";
  };
};

type AsyncTask = LoadingTask | FailedTask | SuccessTask;

const processResult = (task: AsyncTask) => {
  switch (task.state) {
    case "Loading": {
      console.log("로딩중...");
      break;
    }
    case "FAILED": {
      console.log(`에러발생 : ${task.error.message}`);
      break;
    }
    case "SUCCESS": {
      console.log(`성공 : ${task.response.data}`);
      break;
    }
  }
};

서로소 유니온 타입을 사용하는 예시
불필요한 ?(optional chaining 작업을 하지않아도 됨)

함수타입 정의

const func = (a: number, b: number): number => {
  return a + b;
};

const func1 = (name = "David"): void => {
  console.log(`${name}`);
};

return값이 있으면 해당 타입으로 정의
return값이 없으면 void 타입으로 정의

func1(1); // 타입에러

선택적 매개변수 (중요)

필수 매개 변수는 선택적 매개 변수 뒤에 올 수 없다.

(name = "David", tall?: number, age: number) //타입 에러
const self = (name = "David", age: number, tall?: number): void => {
  console.log(`${age}세 ${name}님 반갑습니다.`);
  if (typeof tall === "number") {
    console.log(`${name}님의 키는 ${tall}입니다.`);
  }
};

tall의 타입은 number || undefined 여서 if문, typeof로 값이 들어왔는지 확인 가능

전개연산자 타입

전개연산자는 기본적으로 배열 타입을 가진다.

const getItem = (...rest: [number, number, number]): number => {
  let sum = 0;
  rest.forEach((it) => (sum += it));
  return sum;
};

getItem(1, 2, 3);
getItem(1, 2, 3, 4); // 에러

함수 타입 별칭 + 시그니처

타입별칭 생성 후 함수시그니처 적용

type Add = (a: number, b: number) => number;
const add: Add = (a, b) => a + b;
const add1: Add = (a, b) => a - b;
const add2: Add = (a, b) => a * b;
const add3: Add = (a, b) => a / b;

장점 : 타입만 맞다면 어떤 함수에서도 사용 가능

함수 타입 호환성

함수의 매개변수나 객체인 경우 다운캐스팅이 일어남

type Animal = {
  name: string;
};

let animalFunc = (animal: Animal): void => {
  console.log(animal.name);
};

type Dog = {
  name: string;
  color: string;
};

let dogFunc = (dog: Dog): void => {
  console.log(dog.name);
  console.log(dog.color);
};

//animalFunc = dogFunc; // 에러 
dogFunc = animalFunc;

함수 매개변수의 값은 거의 유일하게 다운캐스팅이 허용되는 상황

매개변수의 개수가 다른 경우

type Func1 = (a: number, b: number) => void;
type Func2 = (a: number) => void;

let func1: Func1 = (a, b) => {};
let func2: Func2 = (a) => {};

func1 = func2;
// func2 = func1; // 에러 

매개변수가 더 많을수록 슈퍼타입 => 업캐스팅 가능

함수 오버로딩

함수의 시그니처를 실제 구현되는 함수 위에다가 사전 작성 => 함수 오버로딩

함수 시그니처 오버로딩

function func(a: number): void;
function func(a: number, b: number, c: number): void;

실제 함수 실행부

function func(a: number, b?: number, c?: number) {
  if (typeof b === "number" && typeof c === "number") {
    console.log(a + b + c);
  } else {
    console.log(a * 20);
  }
}

함수실행&호출

func(1);
func(1, 2); // 실행불가
func(1, 2, 3);

함수를 활용한 타입가드

type Dog = {
  name: string;
  isBark: boolean;
};

type Cat = {
  name: string;
  isScratch: boolean;
};

type Animal = Dog | Cat;

const isDog = (animal: Animal): animal is Dog => {
  return (animal as Dog).isBark !== undefined;
};
const isCat = (animal: Animal): animal is Cat => {
  return (animal as Cat).isScratch !== undefined;
};

const warning = (animal: Animal) => {
  if (isDog(animal)) console.log(animal.isBark ? "짖습니다" : "안짖어요");
  else if (isCat(animal))
    console.log(animal.isScratch ? "할큅니다" : "안할큅니다!");
};

isDog와 isCat 함수를 사용한 직관적인 타입명시

interface 타입추가

interface Person {
  name : string
  agd : number
} | number

위에 형태는 불가 하다

type Type3 = number | string | Person;

const person: Type3 = {
  name: "David",
  age: 20,
};

interface extends를 활용한 확장적 개념

extends 사용 방법

interface Animal {
  name: string;
  age: number;
}

interface Dog extends Animal {
  isBark: boolean;
}

interface Cat extends Animal {
  isScratch: boolean;
}

interface Chicken extends Animal {
  isFly: boolean;
}
const dog: Dog = {
  name: "뽀삐",
  age: 5,
  isBark: true,
};

위 확장을 통해 dog에 Dog라는 타입정의 가능

type extends 사용 방법

type Animal = {
  name: string;
  age: number;
};

interface Dog extends Animal {
  isBark: boolean;
}

interface Cat extends Animal {
  isScratch: boolean;
}

interface Chicken extends Animal {
  isFly: boolean;
}

const dog: Dog = {
  name: "뽀삐",
  age: 5,
  isBark: true,
};

interface 다중확장

interface와 extends를 활용하여 복수의 타입도 확장할 수 있다.

interface DogCat extends Dog, Cat {}

const dogCat: DogCat = {
  name: "뽀삐",
  age: 5,
  isBark: true,
  isScratch: false,
};
profile
하고싶은거 짱많은 주니어 프론트엔드 개발자

0개의 댓글