배운 개념 정리
Any와 Unknown 타입
정의
Any 타입
: 모든 타입을 포괄하는 타입. any 타입의 변수는 어떤 타입의 값이든 할당 받을 수 있으며, 어떤 연산이든 실행할 수 있다. 즉, TypeScript의 타입 검사기는 any 변수에 대해 타입 검사를 수행하지 않는다.Unknown 타입
- any와 비슷하게 어떤 타입의 값이든 할당 받을 수 있다. 하지만 unknown 타입의 변수를 다른 타입의 변수에 할당하거나, 해당 변수의 메서드를 사용하거나, 해당 변수에 연산을 수행하려면 먼저 해당 변수의 타입을 확인하거나 타입 단언을 해야한다.
필요성
Any 타입
- JavaScript 코드를 TypeScript로 마이그레이션하거나 타입 정보가 없는 라이브러리를 사용할 때 매우 유용하다. 또한, 타입 검사를 회피하려는 경우에도 사용할 수 있다. 하지만, 타입 검사를 완전히 무시하기 때문에 사용에 주의가 필요하다.Unknown 타입
- unknown은 any보다 안전한 방법으로 모든 타입의 값을 처리할 수 있다. unknown 타입의 변수를 다른 타입의 변수에 할당하거나 사용하려면 먼저 타입 검사를 수행해야 하므로, 예기치 않은 런타임 에러를 방지할 수 있어, API 응답과 같이 예측할 수 없는 값을 다루는 데 특히 유용
사용법
function anyEaxm() {
let unknownVar: unknown;
let anyVar: any;
let undefinedVar: undefined;
let neverVar: never;
anyVar = unknownVar;
undefinedVar = anyVar;
//! any타입도 never타입에는 Down Casitng이 불가능하다.
//! Type 'any' is not assignable to type 'never'.
//! neverVar = anyVar;
}
function unknownExam() {
// UpCasting 가능
let a: unknown = 1;
let b: unknown = "hello";
let c: unknown = true;
let d: unknown = null;
let e: unknown = undefined;
let unknownVar: unknown;
// DownCasting 불가능
// let num: number = unknownVar;
// let str: string = unknownVar;
// let bool: boolean = unknownVar;
}
Void와 Never 타입
정의
Void 타입
- 보통 함수에서 반환 값이 없을 때 사용하는 타입. void 타입의 변수는 undefined 또는 null만 할당 받을 수 있다.Never 타입
- 절대로 발생하지 않는 값의 타입을 나타낸다. never 타입의 변수에는 어떤 값도 할당할 수 없다.
필요성
Void 타입
- 함수에서 반환 값이 없을 때 반환 타입을 명시적으로 표현하기 위해 사용된다. 함수의 목적을 명확하게 전달하고, 실수로 반환 값을 사용하는 것을 방지한다.Never 타입
- 함수가 절대로 정상적으로 종료되지 않음을 표현하기 위해 사용된다. 예를 들어, 함수가 무한히 실행되거나 항상 예외를 던지는 경우에 never 타입을 사용하여 이를 명시적으로 나타내어 코드의 의도를 명확하게 전달하고, 실수로 이런 함수의 반환 값을 사용하는 것을 방지한다.
사용법
function voidExam() {
// void는 undefined의 슈퍼 타입. undefined가 return되어도 에러가 발생하지 않는다.
function voidFunc(): void {
console.log("void function");
return undefined;
}
let voidVar: void = undefined;
}
function neverExam() {
function neverFunc(): never {
while (true) {}
}
let num: number = neverFunc();
let str: string = neverFunc();
let bool: boolean = neverFunc();
// Down casting 불가능: never 타입에는 어떤 값도 할당할 수 없다.
// let never1: never = 10;
// let never2: never = 'hello';
// let never3: never = true;
}
타입 계층도 관련
기본 타입 간의 호환성
let num1: number = 10;
let num2: 10 = 10;
객체 타입간의 호환성
// Ex1
// Dog 타입은 Animal 타입의 '서브타입'으로 간주되며, Animal 타입은 Dog 타입의 '슈퍼타입'으로 간주된다.
// 그래서 Animal 타입의 변수에 Dog 타입의 값을 할당하는 것(업캐스팅)은 가능하지만, Dog 타입의 변수에 Animal 타입의 값을 할당하는 것(다운캐스팅)은 Dog 타입에 필요한 breed 프로퍼티가 누락되어 있기 때문에 불가능하다.
type Dog = {
name: string;
color: string;
breed: string;
};
let animal: Animal = {
name: "기린",
color: "yellow",
};
let dog: Dog = {
name: "댕댕이",
color: "white",
breed: "포메라니안",
};
// 업캐스팅 가능
animal = dog;
// 다운캐스팅 불가능
// Property 'breed' is missing in type 'Animal' but required in type 'Dog'.
// dog = animal;
// Ex2
type Book = {
name: string;
price: number;
};
type ProgrammerBook = {
name: string;
price: number;
skill: string;
};
let book: Book;
let programmingBook: ProgrammerBook = {
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
skill: "TypeScript",
};
// 업캐스팅 가능
book = programmingBook;
// 다운캐스팅 불가능
// programmingBook = book;
초과 프로퍼티 검사
객체 리터럴을 직접 타입에 할당하거나 함수에 전달할 때, 해당 타입에 정의되지 않은 프로퍼티가 있는지 검사하는 것
// Book1 타입에는 name과 price 두 가지 프로퍼티만 정의되어 있어, Book1 타입의 변수에 객체 리터럴을 할당하거나, Book1 타입의 매개변수를 가진 함수에 객체 리터럴을 전달할 때, 해당 객체 리터럴이 skill이라는 초과 프로퍼티를 가지면 에러가 발생한다.
type Book1 = {
name: string;
price: number;
};
let book2: Book1 = {
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
// 타입정의 했던 객체의 프로퍼티만 사용가능
// skill: "TypeScript"
};
// 하지만,이미 타입 검사가 이루어진 변수를 다루는 경우에는 초과 프로퍼티 검사가 수행되지 않으므로, 이미 ProgrammerBook 타입의 변수에 할당된 객체를 Book1 타입의 변수에 할당하거나, Book1 타입의 매개변수를 가진 함수에 전달하는 것은 가능하다.
let book3: Book1 = programmingBook;
function func(book: Book1) {}
func({
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
// skill: "TypeScript"
});
// 초과 프로퍼티 검사를 피하려면, 변수로 저장해뒀다가 인수로 전달해야한다.
func(programmingBook);
배운 개념 정리
Any와 Unknown 타입
정의
Any 타입
: 모든 타입을 포괄하는 타입. any 타입의 변수는 어떤 타입의 값이든 할당 받을 수 있으며, 어떤 연산이든 실행할 수 있다. 즉, TypeScript의 타입 검사기는 any 변수에 대해 타입 검사를 수행하지 않는다.Unknown 타입
- any와 비슷하게 어떤 타입의 값이든 할당 받을 수 있다. 하지만 unknown 타입의 변수를 다른 타입의 변수에 할당하거나, 해당 변수의 메서드를 사용하거나, 해당 변수에 연산을 수행하려면 먼저 해당 변수의 타입을 확인하거나 타입 단언을 해야한다.
필요성
Any 타입
- JavaScript 코드를 TypeScript로 마이그레이션하거나 타입 정보가 없는 라이브러리를 사용할 때 매우 유용하다. 또한, 타입 검사를 회피하려는 경우에도 사용할 수 있다. 하지만, 타입 검사를 완전히 무시하기 때문에 사용에 주의가 필요하다.Unknown 타입
- unknown은 any보다 안전한 방법으로 모든 타입의 값을 처리할 수 있다. unknown 타입의 변수를 다른 타입의 변수에 할당하거나 사용하려면 먼저 타입 검사를 수행해야 하므로, 예기치 않은 런타임 에러를 방지할 수 있어, API 응답과 같이 예측할 수 없는 값을 다루는 데 특히 유용
사용법
function anyEaxm() {
let unknownVar: unknown;
let anyVar: any;
let undefinedVar: undefined;
let neverVar: never;
anyVar = unknownVar;
undefinedVar = anyVar;
//! any타입도 never타입에는 Down Casitng이 불가능하다.
//! Type 'any' is not assignable to type 'never'.
//! neverVar = anyVar;
}
function unknownExam() {
// UpCasting 가능
let a: unknown = 1;
let b: unknown = "hello";
let c: unknown = true;
let d: unknown = null;
let e: unknown = undefined;
let unknownVar: unknown;
// DownCasting 불가능
// let num: number = unknownVar;
// let str: string = unknownVar;
// let bool: boolean = unknownVar;
}
Void와 Never 타입
정의
Void 타입
- 보통 함수에서 반환 값이 없을 때 사용하는 타입. void 타입의 변수는 undefined 또는 null만 할당 받을 수 있다.Never 타입
- 절대로 발생하지 않는 값의 타입을 나타낸다. never 타입의 변수에는 어떤 값도 할당할 수 없다.
필요성
Void 타입
- 함수에서 반환 값이 없을 때 반환 타입을 명시적으로 표현하기 위해 사용된다. 함수의 목적을 명확하게 전달하고, 실수로 반환 값을 사용하는 것을 방지한다.Never 타입
- 함수가 절대로 정상적으로 종료되지 않음을 표현하기 위해 사용된다. 예를 들어, 함수가 무한히 실행되거나 항상 예외를 던지는 경우에 never 타입을 사용하여 이를 명시적으로 나타내어 코드의 의도를 명확하게 전달하고, 실수로 이런 함수의 반환 값을 사용하는 것을 방지한다.
사용법
function voidExam() {
// void는 undefined의 슈퍼 타입. undefined가 return되어도 에러가 발생하지 않는다.
function voidFunc(): void {
console.log("void function");
return undefined;
}
let voidVar: void = undefined;
}
function neverExam() {
function neverFunc(): never {
while (true) {}
}
let num: number = neverFunc();
let str: string = neverFunc();
let bool: boolean = neverFunc();
// Down casting 불가능: never 타입에는 어떤 값도 할당할 수 없다.
// let never1: never = 10;
// let never2: never = 'hello';
// let never3: never = true;
}
타입 계층도 관련
기본 타입 간의 호환성
let num1: number = 10;
let num2: 10 = 10;
객체 타입간의 호환성
// Ex1
// Dog 타입은 Animal 타입의 '서브타입'으로 간주되며, Animal 타입은 Dog 타입의 '슈퍼타입'으로 간주된다.
// 그래서 Animal 타입의 변수에 Dog 타입의 값을 할당하는 것(업캐스팅)은 가능하지만, Dog 타입의 변수에 Animal 타입의 값을 할당하는 것(다운캐스팅)은 Dog 타입에 필요한 breed 프로퍼티가 누락되어 있기 때문에 불가능하다.
type Dog = {
name: string;
color: string;
breed: string;
};
let animal: Animal = {
name: "기린",
color: "yellow",
};
let dog: Dog = {
name: "댕댕이",
color: "white",
breed: "포메라니안",
};
// 업캐스팅 가능
animal = dog;
// 다운캐스팅 불가능
// Property 'breed' is missing in type 'Animal' but required in type 'Dog'.
// dog = animal;
// Ex2
type Book = {
name: string;
price: number;
};
type ProgrammerBook = {
name: string;
price: number;
skill: string;
};
let book: Book;
let programmingBook: ProgrammerBook = {
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
skill: "TypeScript",
};
// 업캐스팅 가능
book = programmingBook;
// 다운캐스팅 불가능
// programmingBook = book;
초과 프로퍼티 검사
객체 리터럴을 직접 타입에 할당하거나 함수에 전달할 때, 해당 타입에 정의되지 않은 프로퍼티가 있는지 검사하는 것
// Book1 타입에는 name과 price 두 가지 프로퍼티만 정의되어 있어, Book1 타입의 변수에 객체 리터럴을 할당하거나, Book1 타입의 매개변수를 가진 함수에 객체 리터럴을 전달할 때, 해당 객체 리터럴이 skill이라는 초과 프로퍼티를 가지면 에러가 발생한다.
type Book1 = {
name: string;
price: number;
};
let book2: Book1 = {
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
// 타입정의 했던 객체의 프로퍼티만 사용가능
// skill: "TypeScript"
};
// 하지만,이미 타입 검사가 이루어진 변수를 다루는 경우에는 초과 프로퍼티 검사가 수행되지 않으므로, 이미 ProgrammerBook 타입의 변수에 할당된 객체를 Book1 타입의 변수에 할당하거나, Book1 타입의 매개변수를 가진 함수에 전달하는 것은 가능하다.
let book3: Book1 = programmingBook;
function func(book: Book1) {}
func({
name: "한 입 크기로 잘라먹는 타입스크립트",
price: 33000,
// skill: "TypeScript"
});
// 초과 프로퍼티 검사를 피하려면, 변수로 저장해뒀다가 인수로 전달해야한다.
func(programmingBook);