2025년 3월 1일
기본 타입간의 호환성
객체 타입간의 호환성
객체 타입도 기본 타입처럼 슈퍼-서브 타입을 가짐
e.g) Dog 타입의 값이 Animal 타입이 될 수 있지만(업 캐스팅), Animal 타입의 값이 Dog 타입이 될 수 없음(다운 캐스팅)
객체 타입들이 어떤 기준으로 관계를 갖는가?
Book 타입에 ProgrammingBook의 값을 넣는 것은 가능 (업캐스팅) 그런데, 초기화하려고 ProgrammingBook 타입의 객체의 프로퍼티들을 넣으려고 할 때는 안된다고 함
만약, 초과 프로퍼티 검사를 피하려면 새로운 변수를 만든후 원하는 타입의 값(변수)를 할당해서 초기화하도록 한다 (객체 리터럴을 사용하지 않았으므로 허용함)
e.g) let book3: Book = programmingBook;
함수의 매개변수에도 마찬가지임
변수를 초기화하거나 매개변수에 전달할 때, 객체 리터럴을 사용하면 반드시 정의된 프로퍼티만 사용해야함
/**
* 기본 타입간의 호환성
*/
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);
}
| 을 사용
| 를 이용해서 넣을 수 있는 타입은 무한대임
/**
* 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: '',
// }; 오류 발생
& 를 사용
기본 타입을 가지고 intersection 타입을 만들면, 웬만하면 다 never 타입임 (서로 공유하거나 겹치는 값이 없음)
- 보통 intersection 타입은 객체 타입에 많이 사용함
intersection 타입을 만들 때, 각 객체의 프로퍼티가 하나라도 빠지면 오류가 발생함
위에서 살펴본것 처럼, Dog 타입에도 해당 되어야하고, Person 타입에도 해당되어야 함!
/**
* 2. 교집합 - Intersection 타입
*/
let variable: number & string;
// number 타입과 string 타입의 교집합은 never -> 공집합
type Dog = {
name: string;
color: string;
};
type Person = {
name: string;
language: string;
};
type Intersection = Dog & Person;
let intersection1: Intersection = {
name: '',
color: '',
language: '',
};
초기값을 기준으로 타입을 추론
let a = 10;
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];
// [number, string, boolean]으로 타입을 추론함
반환 값을 기준으로 타입을 추론
function func(message = 'hello') {
return 'hello';
}
변수를 선언하고 초기값을 지정하지 않으면 '암묵적인 any 타입'으로 추론됨
명시적으로 any 타입을 정의하는 것과는 다름
암묵적으로 any 타입을 정의하면 타입이 계속 진화함
그런데 암묵적으로 any 타입을 정의하면, 중간에 타입이 바뀔 수도 있고 다른 사람이 짠 코드면 그 변수의 타입을 내가 직접 알아맞춰야 하는 상황이 발생할 수도 있음 -> 따라서, 암묵적으로 any 타입을 추론하도록 하지 않도록 해야함!! (초기값이 없는 경우)
let d;
d = 10;
d.toFixed(); // number 타입으로 진화
// d.toUpperCase(); 오류 발생
d = 'hello';
d.toUpperCase(); // string 타입으로 진화
// d.toFixed(); 오류 발생
const num = 10; // 타입: 10
const str = 'hello'; // 타입: 'hello'
const arr = [1, 2, 3]; // 타입: number[]
const arr2 = [1, 'hello', true]; // 타입: (number | string | boolean)[]
const arr3 = [1, 2, 3] as const; // 타입: [1, 2, 3]
let arr = [1, 'string']; // (number | string)[]
let a = 10;
a = 99;
a = -2;
// let으로 선언한 a 변수에 number 타입의 값이 될 수 있는 모든 숫자를 할당할 수 있음
const b = 100;
b = 20; // 오류 발생
const arr = [1, 2, 3];
arr = [3, 4, 5]; // 오류 발생