본문으로 바로가기

class 생성 및 shortcut

 

js에서 활용하듯 사용하면 됩니다만 사용하기에 앞서 클래스의 속성의 타입을 정의해야 합니다.

class Human {

  public name: string;
  private age: number;
  protected gender: string;
  
  constructor(name: string, age: number, gender: string) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
}

 

그러나 이러한 작성법은 verbose합니다. 좀 더 간략하게 적자면 다음과 같습니다. 편안~

 

class Human {
  constructor(public name: string, private _age: number, protected _gender: string) {}
}

const me: Human = new Human("foo", 35, "male");

console.log(me); // { name: 'foo', _age: 35, _gender: 'male' }

 

tsconfig에서 strictPropertyInitialization 옵션을 켜두면, 위와 같이 반드시 constructor를 통해서 속성들이 초기화되어야 합니다.

  • strictPropertyInitialization => class를 정의할 때 property들이 constructor를 통해 반드시 초기화되어야 한다는 옵션.
class Person {
  // Property 'name' has no initializer and is not definitely assigned in the constructor.
  name: string 
}

만약 strict 옵션을 켜두었지만, constructor 가 아닌 다른 곳에서 값이 들어오는 케이스라면 ! assertion을 통해서 회피할 수 있습니다.

class Person {
  name!: string // strict 옵션을 켜도 에러가 발생하지 않음.
}

 

static

 

인스턴스를 생성하지 않고 곧장 클래스에서 사용할 수 있는 속성을 static이라고 합니다.

class Person {
  static what = "whatever";
  static test = () => console.log("testset");

  constructor(protected _age: number, private _name: string) {}
}

console.log(Person.what);
Person.test();

 

접근 지정자 : public/private/protected

 

default는 public입니다. 그 만큼 public이 사용되는 빈도가 높습니다.

 

최신 JS에서는 #를 이용해 private 속성을 만들 수 있다고는 하는데 아무래도 TS의 방식이 더 직관적이며 다른 코드와 비슷해서 사용하기 더 좋습니다.

 

가장 기본적인 class를 만들어 보았습니다. 사용할 변수는 따로 private로 지정하지 않는 이상 public이 default입니다.

class Person {
  constructor(public name: string, public age: number) {}
}

const foo: Person = new Person("foo", 24);

console.log(foo);

 

 

name 속성을 private로 만들어보았습니다. 이후 외부에서 호출하려고 할 때 오류를 일으킵니다.

private는 정의된 클래스의 extends한 서브 클래스에서도 호출할 수 없습니다.

아, 그리고 모든 언어에서 그랬듯, private한 변수는 _로 시작하는 코딩 컨벤션이 있으니 지켜줍시다.

 

외부에서 호출이 안되니 변경이나 출력도 불가능합니다.

class Person {
  constructor(private name: string, age: number) {}
}

const foo: Person = new Person("foo", 24);

console.log(foo.name); // error! private property

 

protected?

 

private가 서브 클래스에도 호출 불가능하게 만들었다면, protected는 서브 클래스 내부에서는 호출 가능합니다.

참고로 protected도 _를 붙이는 관습이 있습니다.

 

class Person {
  constructor(protected _age: number) {}
}

class Baby extends Person {
  boo() {
    // protected 이므로 서브 클래스에서 사용 가능
    console.log(`I'm ${this._age}`);
  }
}

const da: Baby = new Baby(5);
da.boo();

 

 

 

getter/setter (Accessors)

 

getter/setter는 일반 js에도 있는 기능입니다만, 있다고만 알아두는 게 좋습니다. 왜 그런지 알아봅시다.

 

앞서 private, protected 속성들은 클래스 외부 혹은 서브 클래스 외부 에서는 호출하는 것이 불가능하므로 조작도 불가능함을 알아보았습니다. 외부에서 private, protected 속성을 수정하고 싶을 때는 getter/setter를 활용합니다.

 

get와 set 을 이용한 예시는 다음과 같습니다.

 

class Person {
  constructor(protected _age: number, private _name: string) {}

  get name(): string {
    return this._name;
  }
  get age(): number {
    return this._age;
  }

  set changeAge(age: number) {
    this._age = age;
  }
}

const me = new Person(1000, "vampire");

console.log(me.name); // vampire
me.changeAge = 1001;
console.log(me.age); // 1001

 

그러나, getter와 setter를 작동하고 사용하는 방식이 일반적인 JS/TS와는 다르기 때문에 혼동을 줍니다. 

따라서 속성을 그냥 public으로 만들던가 아니면 다음과 같은 함수를 만드는게 더 편해보입니다.

개인적으로도 getter/setter는 사용하고 있지 않습니다.

 

class Person {
  constructor(protected _age: number, private _name: string) {}

  getName(): void {
    console.log(this._name);
  }
  getAge(): void {
    console.log(this._age);
  }
  changeAge(age: number): number {
    return (this._age = age);
  }
}

const me = new Person(1000, "vampire");

me.getName();
me.getAge();
me.changeAge(50);
console.log(me.getAge());

 

index signature in class

 

일반적인 index signature는 object에서 많이 쓰인다고 알려져 있다.

interface Signature {
  [key: string]: string | number | boolean
}

const obj: Signature = {
  timeout: 1000,
  name: 'none'
}

 

클래스에서도 index signature를 사용할 수 있는데 솔직히 이걸 쓸 일이 있나 모르겠다. 아직까진 없었다...

class MyClass {
  [s: string]: boolean | ((s: string) => boolean)

  check (s: string) {
    return this[s] as boolean
  }
}

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체