인프런 타입스크립트  기초를 통해 공부중이며 제로초님의 유료강좌입니다.

코드를 통으로 가져오지는 않겠습니다.(내가 글을 쓰면서 복습하는게 목적이기때문에 필요한 부분만)

 

타입스크립트에 익숙하지않다면 자바스크립트로 먼저 코드를 작성하고 그 후에 타입스크립트로 변환하도록하자.

 

타입스크립트 (Typescript)

 

오늘은 class와 interface를 더욱 자세히 알아봤다.

클래스는 인터페이스의 확장형(심화)으로 보면 될 듯 하다고 한다.

 

로직에 대한 힌트

인터페이스를 보고 타입을 확인할 수 있기 때문에 해당 로직에 대한 힌트를 얻을 수 있다.

아래 코드에서 인터페이스를 보고 heeJ와 yoon이 div인 것을 알 수 있다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,

    // originData는 클래스
    originData : Example[]
    copyData : Example || null
}

const person = {
    heeJ : document.getElementById('memo-heeJ'),
    yoon : document.getElementById('memo-yoon'),
    originData : [],
    copyData : null
};

 

 

null과 undefined 구분

타입스크립트에서는 null과 undefined를 구분해줘야하는 경우가 있다.

그 경우는 바로 tsconfig.json에 설정에 따라서 인데, "strictNullCheckes" 설정 값에 영향을 받는다.

"strictNullCheckes"가 true일 경우에는 null과 undefined를 구분해주며 false일 경우에는 구분하지 않는다.

 

그리고

"strict"를 true로 설정한다면 기본으로 "strictNullCheckes"도 true가 된다.

{
    "compilerOptions" : {
        "strict" : true
        
        // 보이지는 않지만
        // "strictNullCheckes" : true
    }
}

그렇기 때문에 기본적으로 null과 undefined를 구분이 된다.

때문에 내 데이터가 없을 경우가 존재한다면 null 타입을 추가해줘야한다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
	
    // null을 작성해야한다.
    copyData : Example | null
}

 

만약에 "strict"를 "false"로 변경하게되면?

null을 따로 구분하지 않기 때문에 null을 적어줄 필요가 없다.

하지만 strict가 false이면 타입스크립트의 기능을 극대화해서 사용할 수 없기 때문에 비추한다.

하지만 예제를 보자.

{
    "compilerOptions" : {
        "strict" : false
    }
}
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]

	// null 제거
    copyData : Example
}

 

undefined를 작성하는 대신에 물음표로 대체할 수 있다.

// undefined 예시
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
    copyData : Example | undefined
}

// 물음표 예시
interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]
    copyData? : Example
}

 

"scrictNullChecks"가 true일때

null과 undefined를 구분하고 있으므로 물음표를 추가해도 undefined와 구분이 되므로 null을 작성해줘야한다.

interface People{
    heeJ : HTMLDivElement,
    yoon : HTMLDivElement,
    originData : Example[]

	// 물음표와 null 두개다 포함
    copyData? : Example | null
}

 

제로초님은 보통 자바스크립트로 코드를 짤 때, null은 빈 값을 의도적으로 넣었음을 알리기 위해 사용했다고 한다. 하지만 타입스크립트에서는 "structNullChecks" 때문에 undefined를 사용하는 경우가 많다고한다.

(물음표만 추가하면 되기에..)

 

 

인터페이스와 클래스

인터페이스는 클래스처럼 사용할 수 없다.

interface People{
    heeAge: number;
    yoonAge: number;
}

interFace Person{
    originData : People[],
    copyData? : People | null
}

// 이렇게 쓸 수가 없다.
new People();

아래처럼 클래스 표현이 가능하기는 하다고 한다.

interface People{
    new (yoon: string);
}

 

자바스크립트와 같이 constructor가 필요하며 자바스크립트와는 다르게 private, public, protected 키워드를 지원한다.

자바스크립트에서는 즉시 실행함수 + 클로져를 사용해서 키워드를 흉내냈었는데, 타입스크립트는 지원하고 있기 때문에 최대 장점이라고한다.

(최신문법에는 #을 붙이는 방법으로 지원한다고 한다.)

class Person{
	public age : number;
    protected name : string;
    private address : number;

    constructor(heeJAge, yoonAge){
        // ....
    }
}

const Person(22, 15);

// private로 선언한 address에는 접근이 안됨
Person.address;

private는 class외에 접근이 안되고 public은 모든 곳에서 접근이 가능하다.

protected는 해당 class, 상속받은 자식에서 접근이 된다. (부모에서는 안된다.)

class People{

  // 상속받는 Person에서 접근해야하기 때문에 protected로 선언
  protected heeJAge : number;
  protected yoonAge : number;

  constructor(name: string, age: number){
      // ...
  }
}

new People('hong', 17);

class Person extends People{
	// 여기서 heeJAge와 yoonAge에 접근이 가능하다.
}

 

만약 자바스크립트에서 해당 키워드를 사용해보고 싶다면 컴파일된 파일에서 해당 로직만 사용해봐도된다.

 

클래스에서 new 키워드로 인스턴스를 생성하여 접근하려고 할때 construct내부에 선언한 것을 if문 안에 넣었을 경우 변수의 타입을 인식못하는 경우가 생길수도 있다고한다. 이때는 undefined를 추가해주면된다.

class Person{
    protected value? : number;
    protected number?: number;
    
    constructor(a: boolean, b: boolean){
        if(a){

            // 상속을 하지말고 People코드를 여기에 적으면 물음표를 추가하지 않아도된다.
            return new People(b);
        }
    }
}

class People extends Person{
    private value: number;
    private number: number;
    constructor(mine){
        super(true, mine);
        
        if(true){

            // 상속에 if문안에 있는 이 this.value의 값을 타입스크립트가 모른다.
            this.value = 1;
            this.number = 2;
        }
    }
}

 

protected나 private 키워드를 사용했을 경우 인터페이스를 만드는 것은 말이 안된다고 한다.

protected와 private의 접근 제한을 생각해보자.

(인터페이스는 부모가 되므로 사용될 수 없다.)

 

 

클래스가 지켜야하는 규칙 implements

인터페이스를 구현해서 클래스의 모양을 잡아놓을 수 있다.

클래스는 인스턴스의 모양을 규정짓는거라면 인터페이스는 한단계 더 위에 있으며 클래스의 모양을 규정짓는다.

// 네이밍시에 앞에 I를 추가한다.
interface IName{
    //...
}

class People implements IName{
    //..
}

이때 클래스보다 인터페이스가 더 좁은 집합이어야한다.

범위를 생각해보면 인터페이스를 잘 만들었는지 알 수 있다. 적어도 같게 만들어야한다.

근데 implements는 실제 클래스가 필요없을 때 사용한다고 한다.

클래스의 모양을 정해주고 싶을때 사용한다고 하고 실제로 사용하고 싶다면 class로 변경하면된다.

또한 implements 말고 type aliases를 사용해도 된다.

 

 

+ Recent posts