타입 스크립트 원리 이해
- 타입 정의 기준
- 타입 관계 정의 기준
- 오류 검사 기준
타입 호환성
- 동일한 속성을 갖는 집합을 타입이라고 한다.
- 어떤 타입을 다른 타른으로 변경해도 집합 안의 값인지 판단하는것을 타입 호환성이라고 한다.
- 타입 호환성은 교집합 내에 판단한다.
예) 2, 0, -10, 0.123, Infenitiy

슈퍼 타입, 서브 타입
- 슈퍼 타입 : Down Cast(다운 캐스트)으로 변경될수 있는 타입
- 서브 타입 : Down Cast(다운 캐스트)으로 변경될수 없는 타입
*Down Cast(다운 캐스트) : 슈퍼 타입의 값을 서브타입으로 변경하는것, 변경여부가 상황따라 다르다.
*Up Cast(업 캐스트): 서브타입의 값을 슈퍼타입으로 변경하는 것, 무조건 변경이 가능하다.
// unknow
function unknowEx() {
let a: unknown = 1;
let b: unknown = "a";
let c: unknown = true;
let d: unknown = null;
let e: unknown = undefined;
let f: unknown = () => {};
}
// never
function neverEx() {
function func(): never {
throw new Error();
}
let a: number = func();
let b: string = func();
let c: boolean = func();
// let d: never = 10; // error - up cast
// let e: never = "a"; // error - up cast
// let f: never = true; // error - up cast
}
// void
function voidEx() {
function func(): void {
console.log("hi");
}
let a: void = undefined;
// let b: number = undefined; // error - up cast
}
// any
function anyEx() {
let a: any;
let b: number = 1;
b = a; // any는 down cast에 영향을 받지 않는 특이 케이스
let c: never;
// c = a; // error - 단 never 제외
}
객체 타입 호환성
- 프로퍼티가 일치하는지 검사한다.
- 타입과 일치하지 않는 속성 값을 가진 객체는 슈퍼타입의 객체로 up cast가 불가능하다.
type Info1 = { // super
name: string;
age: number;
}
type Info2 = { // sud : 추가 속성을 가지고 있다.
name: string;
age: number;
address: string;
};
let p1: Info1 = {
name: "kim",
age: 20,
};
let p2: Info2 = {
name: "kim",
age: 20,
address: "seoul",
};
p1 = p2;
// p2 = p1; // error - 객체 속성에 없는 키 값을 가지고 있기때문에
대수 타입
- 여러개의 타입을 합성해서 만드는 타입을 말한다.
- 합집합 타입과 교집합 타입이 존재한다.
- 기본타입 교집합은 단일 타입에서는 사용하기 어렵고, 대부분 객체에서 사용된다.
// 합집합 - union
let a: string | number;
a = 1;
a = "a";
let arr: (number | boolean)[] = [1, true];
type User = {
name: string;
age: number;
};
type Animal = {
name: string;
kind: string;
};
type Union1 = User | Animal;
let user1: Union1 = {
name: "kim",
age: 20,
};
let dog1: Union1 = {
name: "choco",
kind: "dog",
};
let cat1: Union1 = {
name: "choco",
age: 10,
kind: "cat",
};
// let mouse: Union1 = {
// name: "choco", // error - 필수 속성이 없으면 오류
// };
// 교집합 - intersection
let variable: number & string;
// variable = 1; // error - variable는 nerver 타입이다.
type intersection = User & Animal;
// let user2: intersection = { // error
// name: "kim",
// age: 20,
// };
// let dog2 intersection = { // error
// name: "choco",
// kind: "dog",
// };
let cat2: intersection = {
name: "choco",
age: 10,
kind: "cat",
};
타입 추론
- 점진적 타입 시스템에서 가지는 특징
- 타입을 직접 지정하지 않더라고 초기화 값으로 타입이 지정되는 것
- 모든 타입에 타입이 추론되지는 않지만(특히 any) 타입 추론을 잘 사용하면 타입스크립트의 장점을 활용할 수 있다.
// 타입 추론
let l1 = 10;
let l2 = "a";
let l3 = {
id: 1,
name: "kim",
profile: {
address: "seoul",
},
url: ["www", "www2"],
};
let { id, name } = l3;
let [a, b, c] = [1, 'a', true];
function func (msg = 'hi') {
return msg;
}
// 암묵적 any타입: 타입지정을 하지않고 초기화도 하지 않는 변수, 특정 구간내에서만 타입을 가지고 진화할 수 있다.
let d; // any
d =10; // number
d.toFixed();
d ='a'; // string
d.split('a');
// let, const
let n1 = 10; // type : number
const n2 = 10; // type : literal 10
타입 단언
- 타입 추론 상태에서 값을 나중에 가지게되는 변수인 경우, 값을 가지기 전에 타입 체크를 예외처리하는 것
- 파라미터로 넣는 값이나 객체 값을 나중에 넣고 싶은 경우 사용한다.
타입 단언 규칙
- A가 B의 슈퍼타입이거나 서브타입 이어야한다.
// 타입 단언
type User = {
name: string;
age: number;
};
let person = {} as User;
person.name = "kim";
person.age = 20;
let num1 = 10 as number;
let num2 = 10 as never;
let num3 = 10 as unknown;
// let num4 = 10 as string; // error - 타입 교집합이 없는 타입이라 오류
let num4 = 10 as unknown as string;
Non null
- typescript 컴파일러가 undifined 값이 아닐거라고 컴파일 하게 해주는 문법
- 확실한 경우에만 사용
// non null (!)
type Post = {
title: string;
author?: string;
}
let post: Post = {
title: '글1',
author: '작성자1' // optional channing
};
const len: number = post.author!.length;
타입 가드
- 조건문 등을 사용하려 넓은 타입에서 좁은 타입으로 줄여가는 코드를 작성하는 것
// 타입 좁히기
type Person = {
name: string;
age: number;
};
function func(val: number | string | Date | null | Person) {
if (typeof val === "number") {
val.toFixed();
} else if (typeof val === "string") {
val.toLowerCase();
} else if (val instanceof Date) {
val.getTime();
} else if (val && "age" in val) {
console.log(val.name + val.age);
}
}
서로소 유니온 타입
- 교집합이 없는 타입으로만 만든 유니온 타입
// 서로소 유니온 타입
type Admin = {
tag: "Admin";
name: string;
kickCount: number;
};
type Member = {
tag: "Member";
name: string;
point: number;
};
type Guest = {
tag: "Guest";
name: string;
visitCount: number;
};
type User = Admin | Member | Guest;
function login(user: User) {
// 안 좋은 예
// if('kickCount' in user){
// console.log(user.kickCount)
// }else if('point' in user){
// console.log(user.point);
// }else{
// console.log(user.visitCount);
// }
// }
// if (user.tag === "Admin") {
// console.log(user.kickCount);
// } else if (user.tag === "Member") {
// console.log(user.point);
// } else {
// console.log(user.visitCount);
// }
switch (user.tag) {
case "Admin":
console.log(user.kickCount);
break;
case "Member":
console.log(user.point);
break;
case "Guest":
console.log(user.visitCount);
break;
default:
break;
}
}
// 비동기 작업 처리 예
type LoadTask = {
state: "LOAD";
};
type FailedTask = {
state: "FAILED";
error: {
message: string;
};
};
type SuccessTask = {
state: "SUCCESS";
response: {
data: string;
};
};
// type AsyncTask = {
// state: "LOAD" | "FAILED" | "SUCCESS";
// error?: {
// message: string;
// };
// response?: {
// data: string;
// };
// };
type AsyncTask = LoadTask | FailedTask | SuccessTask;
function processResult(task: AsyncTask) {
switch (task.state) {
case "LOAD":
console.log("로딩중");
break;
case "FAILED":
console.log("에러" + task.error.message);
break;
case "SUCCESS":
console.log("성공" + task.response.data);
break;
}
}
const loading: AsyncTask = {
state: "LOAD",
};
const failed: AsyncTask = {
state: "FAILED",
error: {
message: "msg..",
},
};
const success: AsyncTask = {
state: "SUCCESS",
response: {
data: "data..",
},
};
출처
- 한 입 크기로 잘라먹는 타입스크립트(TypeScript)
'Frontend > TypeScript' 카테고리의 다른 글
[TypeScript] TypeScript 인터페이스/클래스/제너릭 타입 이해 - 4 (0) | 2024.04.14 |
---|---|
[TypeScript] TypeScript 함수 타입 이해 - 3 (0) | 2024.04.14 |
[TypeScript] TypeScript 기본 문법 - 1 (0) | 2024.04.14 |
TypeScript 동작 원리와 생태계 이해하기 (0) | 2024.04.12 |
TypeScript의 등장 | tsconfig.json (0) | 2024.04.12 |