class Car {
constructor(public color:string){
// 이 부분은 생략이 가능하다.
// 파라미터들을 써주기만 하면 TS가 알아서 constructor 함수를 만들어준다.
this.color = color;
}
start(){
console.log("start");
}
}
const bmw = new Car("red");
bmw.start();
public
- 자식 클래스, 클래스 인스턴스 모두 접근가능(default)private
- 해당 클래스 내부에서만 접근 가능(private 키워드 대신 # 사용 가능)protected
- 자식 클래스에서 접근 가능구분 | 선언한 클래스 내 | 상속받은 클래스 내 | 인스턴스 |
---|---|---|---|
private | ⭕ | ❌ | ❌ |
protected | ⭕ | ⭕ | ❌ |
public | ⭕ | ⭕ | ⭕ |
static
을 사용하면 정적 멤버 변수, 메서드를 만들 수 있다. 클래스.
으로 접근이 가능하다.
class Car {
// color: string;
static wheels = 4;
constructor(public color:string){
this.color = color;
}
start(){
console.log("start");
console.log(Car.wheels);
}
}
const bmw = new Car("red");
readonly
키워드를 클래스 속성 이름 앞에 추가하면 읽기 전용 속성이 되어 속성을 수정할 수 없다.
class Word {
constructor(
public readonly term :string,
public readonly def :string
){}
}
추상 클래스는 클래스 앞에 abstarct
키워드를 사용한다. 추상 클래스는 new를 이용해서 객체를 만들 수 없고 상속을 할 때만 사용할 수 있다.
👉 오로지 상속만을 위한 것
추상 클래스는 공통된 속성과 메소드를 갖도록 해주는 청사진
을 만들기 위해 사용한다.
추상 클래스 안에는 추상 메서드
를 구현할 수 있다. 추상 메서드 안에 내용은 추상 메서드가 아닌 상속받은 쪽에서 구현 해야한다.
type Words = {
// property에 대해 모르고 타입만 알 때 유용
[key:string]: string
}
class Dict {
private words: Words
constructor(){
// 수동으로 초기화
this.words = {}
}
// 클래스를 타입으로 쓸 수 있다!
add(word:Word){
// 사전에 단어가 존재하지 않으면 추가
if(!this.words[word.term]){
this.words[word.term] = word.def;
}
}
def(term:string){
return this.words[term];
}
}
class Word {
constructor(
public term :string,
public def :string
){}
}
const dict = new Dict();
const kimchi = new Word("kimchi", "한국의 음식");
dict.add(kimchi);
dict.def("kimchi");
타입은 객체를 설명하는데도 쓸 수 있고 타입 alias를 만드는데도 사용할 수 있고 특정 값을 가지도록 제한할 수도 있다.
👉 타입은 인터페이스에 비해 더 다양하게 활용할 수 있다.
아래처럼 연산자
를 이용해서 타입이 특정값을 가지게 할 수 있다.
type Team = "red" | "blue" | "yellow";
type Health = 1 | 5 | 10
type Player = {
nickname:string,
team:Team,
health: Health
}
const nico:Player = {
nickname: "yuni",
team: "red",
health: 5
}
인터페이스는 타입과 달리 객체의 모양을 특정해주는 용도로만 사용한다.
type Team = "red" | "blue" | "yellow";
type Health = 1 | 5 | 10
interface Player {
nickname:string,
team:Team,
health: Health
}
const nico:Player = {
nickname: "yuni",
team: "red",
health: 5
}
extends
키워드를 이용해 인터페이스를 다른 인터페이스에 상속할 수 있다.
interface User{
name:string
}
interface Player extends User {
}
const yuni:Player = {
name: "yuni"
}
// 타입으로도 아래와 같이 작성하면 위 코드와 동일하게 사용할 수 있다.
type User = {
name:string
}
type Player = User & {
}
const yuni:Player = {
name: "yuni"
}
🤔 인터페이스와 타입의 차이점
✔ 확장하는 방법(상속) : 인터페이스는 extends, 타입은 &
✔ 선언적 확장 : type은 새로운 속성을 추가하기 위해서 다시 같은 이름으로 선언할 수 없지만, interface는 아래 코드처럼 항상 선언적 확장이 가능하다.
interface User { name: string } interface User { lastName: string } interface User { health: number }
✔ interface는 객체에만 사용이 가능하다.
implements
를 사용해서 인터페이스의 속성과 메소드를 클래스에서 구현하도록 할 수 있다.
interface User {
firstName:string,
lastName:string
sayHi(name:string):string
fullName():string
}
interface Human {
health:number,
}
class Player implements User, Human {
constructor(
public firstName:string,
public lastName:string,
public health:number,
){}
fullName(){
return `${this.firstName} ${this.lastName}`;
}
sayHi(name:string){
return `Hello ${name} My name is ${this.fullName()}`;
}
}
인터페이스는 타입스크립트에서만 존재하기 때문에 추상 클래스를 상속하는 것보다 코드가 가볍다.
typescript type과 interface의 차이
interface SStorage<T> {
[key:string]: T
}
class LocalStorage<T> {
// 제네릭을 전달할 수 있다.
private storage: SStorage<T> = {}
set(key:string, value:T){
this.storage[key] = value;
}
remove(key:string){
delete this.storage[key];
}
get(key:string): T {
return this.storage[key];
}
clear(){
this.storage = {};
}
}
const stringStorage = new LocalStorage<string>();
stringStorage.get("cat");