Notice
Recent Posts
Recent Comments
Link
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

일상

타입스크립트 복습 2 본문

개발

타입스크립트 복습 2

콜리/khgeung 2026. 2. 3. 19:56

1. 타입스크립트 이해 - 집합

  • number 타입과 number literal 타입

  • 타입 호환성 : 어떤 타입을 다른 타입으로 취급해도 괜찮은지 판단하는 것

  • 더 큰 타입의 값을 더 작은 타입의 값에 할당하는 것은 불가
    • 업캐스팅(UpCasting) : 작은 곳에서 큰 곳으로 (모든 상황에 가능)
    • 다운캐스팅(DownCasting) : 큰 곳에서 작은 곳으로 (대부분의 상황에 X)
let num1 : number = 10;
let num2 : 10 = 10;
num1 = num2; //업캐스팅 
num2 = num1; //에러

2. 타입 계층도

/**
 * Unknown 타입 : 전체 집합 (모든 타입들을 포함)
 */

function unknownExam() {
  //업캐스팅 (가능)
  let a: unknown = 1;
  let b: unknown = "hello";
  let c: unknown = true;
  let d: unknown = null;
  let e: unknown = undefined;

  let unknownVar: unknown;

  //다운캐스팅 (에러)
  //   let num: number = unknownVar;
  //   let str: string = unknownVar;
  //   let bool: boolean = unknownVar;
}
/**
 * Never 타입
 */
function neverExam() {
  //이 함수가 반환하는 것은 공집합이다 (아무것도 없다)
  //어떤 값도 저장되어선 안 될때 사용한다.
  function neverFunc(): never {
    while (true) {}
  }
  let num: number = neverFunc();
  let str: string = neverFunc();
  let bool: boolean = neverFunc();

  // let never1: never = 10;
  // let never2: never = "string";
  // let never3: never = true;
}
/**
 * Void 타입
 */
function voidExam() {
  function voidFunc(): void {
    console.log("hi");
    return undefined;
  }

  let voidVar: void = undefined;
}

/**
 * any 타입 : never 제외 다운캐스팅 모두 가능
 */
function anyExam() {
  let unknownVar: unknown;
  let anyVar: any;
  let undefinedVar: undefined;
  let neverVar: never;

  //다운캐스팅 가능
  anyVar = unknownVar;
  undefinedVar = anyVar;
  //never은 어느타입도 다운캐스팅 불가 (any도 불가)
  //neverVar = anyVar;
}

3. 객체 타입의 호환성

/**
 * 기본 타입간의 호환성
 */

let num1: number = 10;
let num2: 10 = 10;

num1 = num2;

/**
 * 객체 타입간의 호환성
 * -> 어떤 객체 타입을 다른 객체 타입으로 취급해도 괜찮은가?
 */

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

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

let animal: Animal = {
  name: "기린",
  color: "yellow",
};

let dog: Dog = {
  name: "돌돌이",
  color: "brown",
  breed: "진도",
};

animal = dog;
//dog = animal;

type Book = {
  name: string;
  price: number;
};

type ProgrammingBook = {
  name: string;
  price: number;
  skill: string;
};

let book: Book;
let programmingBook: ProgrammingBook = {
  name: "한 입 크기고 잘라먹는 리액트",
  price: 33000,
  skill: "reactjs",
};

book = programmingBook;
//programmingBook = book;

/**
 * 초과 프로퍼티 검사
 */

let book2: Book = {
  name: "한 입 크기고 잘라먹는 리액트",
  price: 33000,
  //skill: "reactjs",
};

let book3: Book = programmingBook;

function func(book: Book) {}
func({
  name: "한 입 크기고 잘라먹는 리액트",
  price: 33000,
  //skill: "reactjs",
});
func(programmingBook);

4. 대수 타입

/**
 * 대수 타입
 * -> 여러개의 타입을 합성해서 새롭게 만들어낸 타입
 * -> 합집합 타입과 교집합 타입이 존재합니다
 */

/**
 *1. 합집합 - Union 타입
 */
let a: string | number | boolean | undefined | null | {};
a = 1;
a = "hello";

a = true;
let arr: (number | string | boolean)[] = [1, "hello", true];

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

type Person = {
  name: string;
  language: string;
};

type Union1 = Dog | Person;

let union1: Union1 = {
  name: "",
  color: "",
};

let union2: Union1 = {
  name: "",
  language: "",
};

let union3: Union1 = {
  name: "",
  color: "",
  language: "",
};

// let union4: Union1 = {
//   name: "",
// };

/**
 * 2. 교집합 타입 - Intersection 타입
 */

let variable: number & string;

type Intersection = Dog & Person;

let Intersection: Intersection = {
  name: "",
  color: "",
  language: "",
};

5. 타입 추론

  • let으로 타입 지정 안하고 변수 선언 -> number, string 등과 같은 범위로 타입을 추론해준다.
  • const 로 타입을 지정하면 해당 값이 리터럴 타입으로 들어간다. ex) const a  = 10 -> a : 10
/**
 * 타입 추론
 */

let a = 10; //number 타입으로 추론 (범용적) = 타입 넓히기
let b = "hello";
let c = {
  id: 1,
  name: "홍길동",
  profile: {
    nickname: "winterlood",
  },
  urls : {"https://winterlood.com"},
};

let { id, name , profile} = c;

let [one, two, three] = [1, "hello", true];

function func(message="hello") {
    return "hello";
}

let d; //타입을 정해주지 않으면 암묵적인 any 타입으로 추론됨
// d:any 라고 정의해주는 것과 다름 (이때는 진화 안함)
d = 10; //any -> number 타입으로 변경됨 (=진화 o)
d.toFixed();

d="hello"; //string 타입으로 변경됨
d.toUpperCase();
//d.toFixed();

const num = 10; //상수는 리터럴 타입(10)으로 정의됨
const str = "hello";

//배열은 모든 요소를 확인하여 공통된 타입으로 추론함
let arr = [1, "string"]; //배열 : string | number로 추론됨

6. 타입 단언

/**
 * 타입 단언 type assertion
 */

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

//타입 단언
let person: any = {} as Person; //키워드로 타입을 명시해준다 (Person타입으로 간주하도록)
person.name = "홍길동";
person.age = 27;

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

let dog = {
  name: "돌돌이",
  color: "brown",
  breed: "진도", // Dog타입으로 단언하여 해당 프로퍼티가 오류가 나지 않음
} as Dog;

/**
 * 타입 단언의 규칙
 * 값 as 단언 <- 단언식
 * A as B
 * A가 B의 슈퍼타입이거나
 * A가 B의 서브타입이어야 함
 */

let num1 = 10 as never; //A(10)이 B(never:모든 타입의 서브타입)의 슈퍼타입
let num2 = 10 as unknown; //A(10)가 B(unknown)의 서브타입

//A와 B는 교집합이 없는 타입 -> 에
//number -> unknown -> string 은 가능 : 다중 단언, 지양해야 함
let num3 = 10 as unknown as string;

/**
 * const 단언
 */

let num4 = 10 as const; //num : 10로 추론 -> const로 정의한 것과 같이 추론함

let cat = {
  name: "야옹이",
  color: "yellow",
} as const; //모든 프로퍼티를 readonly로

// cat.name = "";

/**
 * Non Null 단언
 */

type Post = {
  title: string;
  author?: string;
};

let post: Post = {
  title: "게시글1",
  author: "홍길동",
};

//null or undefined 일 경우 대비로 ? 사용(옵셔널 체이닝)
//number | undefined 형식은 number 에 할당 불가
//? -> ! 로 변경 : null 또는 undefined 가 아닐 것이라고 알림 -> number 타입 할당 가능
const len: number = post.author!.length;

7. 타입 좁히기

/**
 * 타입 좁히기
 * 조건문 등을 이용해 넓은 타입에서 좁은 타입으로
 * 타입을 상황에 따라 좁히는 방법을 이야기하기
 */

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

//value => number : toFixed
//value => string : toUpperCase
//value => Date : getTime
//value => Person : name은 age살 입니다.
function func(value: number | string | Date | null | Person) {
  if (typeof value === "number") {
    //number 타입으로 보장됨
    console.log(value.toFixed());
  } else if (typeof value === "string") {
    //string 타입으로 보장됨
    console.log(value.toUpperCase());
  } else if (value instanceof Date) {
    //typeof value === "object" => null도 이 조건을 통과하므로
    //아래 코드에서 에러가 발생한다.
    console.log(value.getTime());
  } else if (value && "age" in value) {
    //person은 클래스가 아니므로 instanceof 사용 불가
    console.log(`${value.name}은 ${value.age}살 입니다`);
  }
}

8. 서로소 유니온 타입

/**
 * 서로소 유니온 타입
 * 교집합이 없는 타입들로만 만든 유니온 타입을 말함
 */

type Admin = {
  tag: "ADMIN";
  name: string;
  kickCount: number;
};

type Member = {
  tag: "MEMBER";
  name: string;
  point: number;
};

type Guest = {
  tag: "GUEST";
  name: string;
  visitCount: number;
};

//tag : "ADMIN" 과 tag:"MEMBER" 이 다르므로 Admin 과 Member 타입 간의 교집합은 존재 X => 서로소
//서로소 Union 타입
type User = Admin | Member | Guest;

//Admin -> {name}님 현재까지 {kickCount}명 강퇴했습니다.
//Member -> {name}님 현재까지 {point} 모았습니다.
//Guest -> {name}님 현재까지 {visitCount}번 오셨습니다.
function 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;
    }
  }

  //   if (user.tag === "ADMIN") {
  //     //admin 타입
  //     console.log(`${user.name}님 현재까지${user.kickCount}명 강퇴했습니다.`);
  //   } else if (user.tag === "MEMBER") {
  //     //member 타입
  //     console.log(`${user.name}님 현재까지${user.point}모았습니다.`);
  //   } else {
  //     //guest 타입
  //     console.log(`${user.name}님 현재까지${user.visitCount}번 방문하셨습니다.`);
  //   }
}

/**
 * 복습겸 한가지 더 사례
 */

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

type FailedTask = {
    state : "FAILED";
    error : {
        message : string;
    };
};

type SuccessTask = {
    state : "SUCCESS",
    response : {
        data : string;
    };
};

//비동기 작업의 결과를 처리하는 객체
type AsyncTask = LoadingTask | FailedTask | SuccessTask;

//로딩 중 -> 콘솔에 로딩중 출력
//실패 -> 실패 : 에러 메시지를 출력
//성공 -> 성공 : 데이터를 출력
function 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;
        }
    }
    
}

const loading : AsyncTask = {
    state : "LOADING",
};

const failed : AsyncTask = {
    tate ="FAILED",
    error :{
        message : "오류 발생 원인은 ~~~",
    },
};

const success : AsyncTask = {
    state : "SUCCESS",
    response : {
        data : "데이터 ~~",
    },
}

'개발' 카테고리의 다른 글

타입스크립트 복습 1  (0) 2026.01.06
React Native 초기 설정 가이드  (0) 2025.03.30