or (|)
유니온 타입(union type) let value: number | string | boolean = 10;
value = "a";
value = true;
let obj: { name: string; age: number } | { skill: string } = {
name: "john",
age: 20,
};
obj = { skill: "front" };
let arr: number[] | string[] = [1, 2, 3];
arr = ["a", "b", "c"];
let mixArr: (string | number)[] = [1, "a", 2, "b"];
function printValue(value: number | string): void {
console.log(value);
}
printValue(10);
printValue("a");
function printValue2(
value: number | string | boolean
): number | string | boolean {
return value;
}
printValue2(10);
printValue2("a");
printValue2(true);
toUpperCase()
를 사용할 때 발생하는 오류let value: string | number = "hello, world";
console.log(value.toUpperCase()); // HELLO, WORLD
// 위의 코드를 함수로 만들면 오류가 남
function printProcess(value: string | number): void {
console.log(value.toUpperCase())
}
printProcess("hello, world") // 오류
타입 가드 (Type Guard)
typeof
, instanceof
(instanceof는 뒤에서 배울 것임)타입가드
를 활용하여 오류를 막는 예시function printProcess(value: string | number): void {
// 타입 가드(Type Guard)
if (typeof value === "string") {
console.log(value.toUpperCase());
}
}
printProcess("hello, world");
function printProcess(value: string | number): void {
// 타입 가드(Type Guard)
if (typeof value === "string") {
console.log(value.toUpperCase());
}
// 타입 가드(Type Guard)
if (typeof value === "number") {
console.log(value.toFixed(2));
}
}
printProcess("hello, world");
printProcess(10);
다만, 타입이 더 확장되었을 경우 사용에 주의해야 함
function printProcess(value: string | number): void {
// 타입 가드(Type Guard)
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
printProcess("hello, world");
printProcess(10);
function printProcess(value: string | number): string | number {
return value;
}
const value1 = printProcess("hello, world");
const value2 = printProcess(10);
// value1과 value2는 함수 실행 값에 따라 문자열이 될 수도 숫자가 될 수도 있다
// 따라서 console.log(value1.toUpperCase())와 같이 사용할 수 없음
if (typeof value1 === "string") console.log(value1);
if (typeof value2 === "number") console.log(value2);
and (&)
인터섹션 타입(intersection type)// string과 number를 동시에 만족하는 것은 불가하므로 어떤 값도 할당 불가
let value: string & number;
// ex)
let value: { name: string; age: number } & { skill: string } = {
name: "john",
age: 20,
skill: "front",
};
// ex2) 같은 속성에 댜른 타입을 지정하면 충돌하게 됨
let value2: { name: string; age: number } & { skill: string; name: number } =
// name에 string과 number가 충돌
// 인터섹션 타입을 사용할 때는 속성이 충돌되지 않게 개발자가 신경을 써야 함
{
// name:: "john",
age: 20,
skill: "front",
};
// ex3) 속성 안의 속성값에 대해 적용하면 병합이 됨
let value3: { name: string; address: { city: string } } & {
address: { zipcode: number };
} = {
name: "john",
address: {
city: "seoul",
zipcode: 111,
},
};
인터섹션 타입
은 any
와 결합하면 any
로 평가됨any
와 결합이 되면 같이 결합된 것은 의미가 없어짐let value: { namd: string } & any = {
name: "철수",
age: 29,
};
unknown
은 인터섹션 타입
과 함께 사용할 수 없음let value: { name: string } & unknown = {
name: "철수",
};
인터섹션 타입
이 never
와 결합하면 모두 never
로 평가됨let value: { name: string } & never;
function combine(a: number | string, b: number | string): number | string {
// 타입스크립트는 문자열 + 숫자를 허용하지 않음
// 자바스크립트는 이 경우 숫자를 문자열로 변환하여 문제 없이 문자열 결합을 시킴
if (typeof a === "string" && typeof b === "string") return `${a}${b}`;
if (typeof a === "number" && typeof b === "number") return a + b;
throw new Error("Invalid arguments");
// return `${a}${b}` 이걸로 조건이 만족되지 않을 땐 저 값을 반환시킬 수도 있음
}
const result = combine(10, "a");
console.log(result);
타입 가드
로 해결 function combine(a: number | string, b: number | string): number | string {
if (typeof a === "number" && typeof b === "number") return a + b;
else return `${a}${b}`;
}
const result = combine(10, "a");
// 타입 가드
if (typeof result === "string") console.log(result.toUpperCase()); //10A
함수 오버로드
로 해결// 함수 오버로드로 경우의 수를 좁혀줌
// 해당 하는 경우를 직접적으로 적어준다
function combine(a: number, b: string): string; // (1)의 오버로드 시그니처
function combine(a: string, b: number): string; // (2)의 오버로드 시그니처
function combine(a: number | string, b: number | string): number | string {
if (typeof a === "number" && typeof b === "number") return a + b;
else return `${a}${b}`;
}
const result = combine(10, "a"); // (1)
const result2 = combine("a", 10); // (2)
// 타입스크립트는 오버로드에 더 의존함
// 따라서 number + number = string으로 오버로드 시그니처를 작성하면
// string으로 판단하고 toUpperCase에 넣지만 숫자이므로 오류 발생
console.log(result.toUpperCase()); // 10A
console.log(result2.toUpperCase()); // A10
함수 오버로드
다른 예시 function printReturnValue(value: number): number;
function printReturnValue(value: string): string;
function printReturnValue(value: number | string): number | string {
if (typeof value === "number") return value.toFixed(1);
else return value;
}
const res = printReturnValue(10);
function showInfo(name: string): string; // number가 없는 경우
function showInfo(name: string, age: number): string; // number가 있는 경우
function showInfo(name: string, age?: number): string {
if (age) {
return `Hello, ${name}, ${age}`;
} else {
return `Hello, ${name}`;
}
}
console.log(showInfo("john"));
console.log(showInfo("john", 20));
타입 추론
undefined
까진 추론해주지 않음타입 표명
타입 별칭 (type alias)
type(키워드)
+ 타입명(첫 글자 대문자)
= 타입type MyTypeName = string | number | boolean;
type Person = { name: string; age: number };
리터럴 타입
기본 자료형
만 가능, 참조 자료형
은 값이 바뀔 수 있으므로 리터럴 타입이 추론 안 됨참조 자료형
은 타입 표명으로 명시해줘야 한다.