readonly
>const user: {
readonly name: string; // 읽기 전용 속성이 됨
age: number;
gender?: string;
// 옵셔널은 string | undefined와 똑같음
} = {
name: "john",
age: 20,
};
// user.name = "james"; 변경하려고 하면 에러가 남
console.log(user); // { name: 'john', age: 20 }
const arr: readonly number[] = [1, 2, 3];
// arr[0] = 10; readonly 때문에 에러 남
// arr.push(4); readonly 때문에 에러 남
console.log(arr); // [ 1, 2, 3 ]
인덱스 시그니처
>const user: {
[key: string]: string | number;
// 동일한 속성일 경우, 인덱스 시그니처로 한 번에 표현
} = {
name: "john",
gender: "male",
address: "seoul",
age: 20, // 추가하고 싶다면 위의 타입에 추가해야 함
};
타입 별칭 (type alias)
>type ID = string | number;
// string, |, number는 타입 시스템에 있음
// string | number처럼 묶어서 사용하는 것은 타입 시스템에 없음
// 그래서 원하는 대로 조합해서 사용하는 것
let id: ID = "a";
id = 12345;
객체
타입 별칭type User = {
// 객체 형식으로 타입 별칭을 만들어서 사용 가능
name: string;
age: number;
};
const user2: { name: string; age: number } = {
name: "john",
age: 20,
};
// 코드 가독성이 좋아짐
const user: User = {
name: "john",
age: 20,
};
함수
타입 별칭type SumFunc = (n1: number, n2: number) => number;
// 함수 형식으로 만들어서 사용 가능
const sum: SumFunc = function sum(n1, n2) {
return n1 + n2;
};
제네릭
타입 별칭type Car<U, T> = {
name: string;
color: U;
// option: null | string | { giftcard: string };
option: T;
};
const car: Car<string, null> = {
name: "benz",
color: "black",
option: null,
};
const car2: Car<string, string> = {
name: "benz",
color: "black",
option: "key",
};
const car3: Car<string, { giftcard: boolean }> = {
name: "benz",
color: "black",
option: {
giftcard: true,
},
};
튜플
타입 별칭type Point = [number, number];
const point: Point = [10, 20]; // 좌표
인터섹션
타입 별칭type Nameable = {
name?: string;
};
type Ageable = {
age?: number;
};
type Person = Nameable & Ageable & { gender?: string };
// 인터섹션 타입 &으로 병합하여 사용 가능
const person: Person = {
name: "john",
age: 20,
gender: "male",
};
리터럴
타입 별칭type Direction = "LEFT" | "RIGHT" | "UP" | "DOWN";
const direction: Direction = "RIGHT";
type Gender = "femail" | "male" | "natural";
const gender: Gender = "male";
조건부
타입 별칭type IsString<T> = T extends string ? "yes" : "no";
const test1: IsString<string> = "yes";
const test2: IsString<number> = "no";
키 선택
타입 별칭keyof
키워드 : 키만 추출해서 유니온으로 묶어줌type Persons = {
name: string;
age: number;
address: string;
};
type PersonKeys = keyof Persons;
// 키만 추출해서 유니온으로 묶어줌
// "name" | "age" | "address"
const key: PersonKeys = "address";
인덱스 시그니처
타입 별칭인덱스 시그니처
와 고정 속성
을 복합으로 사용 가능type UseMap = {
age: number; // 고정 속성
[key: string]: string | number; // 인덱스 시그니처
};
let users: UseMap = {
name: "john",
age: 20,
gender: "male",
address: "seoul",
};
인터페이스
>interface 타입명 {키: 키 타입}
interface User {
name: string;
age: number;
}
const user: User = {
name: "john",
age: 20,
};
?
) 인터페이스interface User {
name: string;
age?: number; // 옵셔널(?) 사용 가능
}
const user: User = {
name: "john",
};
readonly
인터페이스interface User {
name: string;
readonly age: number; // 읽기 전용
}
const user: User = {
name: "john",
age: 20,
};
// user.age = 20 // 해당 속성에 동적 추가 시 에러 발생
인덱스 시그니처
인터페이스interface User {
name: string; // 고정 속성
[key: string]: string; // 인덱스 시그니처
}
const user: User = {
name: "james",
gender: "male",
};
함수 타입
인터테이스type SumFunc = (a: number, b: number) => number;
const sum: SumFunc = (a, b) => a + b;
interface IsSumFunc {
(a: number, b: number): number;
name: string; // 에러 발생 안 함
// 함수 기본 속성에 arguments, length, name이 있기 때문
// caller는 안 됨, 우리가 지정할 수 있는 값이 아님
// 이 외의 값을 지정하면 에러 발생
}
const sum2: IsSumFunc = (a, b) => a + b;
선언 병합(Declaration Merging)
이라고도 함// 인터페이스는 자동으로 합쳐짐
interface User {
name: string;
}
interface User {
age: string;
}
// 타입 별칭은 에러가 난다
type TUser = {
name: string;
};
type TUser = {
age: number;
};
interface Shape {
color: string;
}
interface Circle extends Shape { // 상속 가능
radius: number;
color: string;
}
const circle: Circle = {
radius: 10,
color: "red",
};
// type으로 상속처럼 보이게 작성할 수 있음
// 하지만 상속이 아닌 인터섹션 타입을 이용한 것
type Shape = {
color: string;
};
type Circle = Shape & {
radius: number;
};
const circle: Circle = {
radius: 10,
color: "red",
};
interface Person {
name: string;
age: number;
}
const person: Person = {
name: "john",
age: 20,
};
interface Address {
city: string;
zipcode: string;
}
// 유지 보수나 가독성면에서 훨씬 더 이점을 가질 수 있다
// Person, Address 처럼 나열해서 다중 상속
interface Employee extends Person, Address {
employeeId: string;
}
const employee: Employee = {
name: "철수",
age: 21,
employeeId: "1234",
city: "seoul",
zipcode: "3111",
};
실무에서는 단축 메서드 많이 사용
interface Animal {
name: string;
sound: () => void;
// sound(): void (단축 메서드)
}
interface Pet extends Animal {
play: () => void;
// play(): void (단축 메서드)
}
const dog: Pet = {
name: "뽀삐",
sound: () => {
console.log("멍멍");
},
// sound() {console.log("멍멍");} (단축 메서드)
play: () => {
console.log("놀기");
},
// play() {console.log("놀기");} (단축 메서드)
};
// 타입 가드를 한 번 사용 후 호출
if (dog.play) dog.play();
interface Container<U> {
value: U;
}
// 제네릭은 치환한다고 생각하면 편하다.
// 1) const box: Box<number, boolean>에서
// number가 T, boolean이 U로 넘어오고
// 2) Container<U>에서 원하는 값을 들고와서
// 3) interface Container<U>로 보낸다
interface Box<T, U> extends Container<U> {
label: string;
scale?: T;
inStock?: U;
}
const container: Container<number> = {
value: 10,
};
const box: Box<number, boolean> = {
label: "grid box",
value: true,
scale: 10,
};