TypeScript 4.3 신기능 정리

목차

  • 클래스 오버라이드 플래그
  • 템플릿 문자열 타입 개선
  • ECMAScrpt #private 클래스 요소
  • ConstructorParameters를 추상클래스에서 사용
  • 항상 참인 Promise 검사
  • Import 자동완성
  • 편집기 지원 @link 태그
  • Enum과 임의의 값 비교 불가

클래스 오버라이드 플래스

부모 클래스를 상속받은 자식 클래스가 부모의 메소드를 재정의할 수 있는데, 이때 어떠한 이유로 부모 클래스의 해당 메소드가 삭제되는 경우, 자식 클래스에서는 별도의 오류를 발생시키지 않아 해당 메소드가 오버라이드된 것인지 아닌지 확인하기 어렵다.

 

class SomeComponent{
    show(){
        console.log('show a1');
    }
    hide(){
        console.log('hide a1');
    }
}

class SpecializedComponent extends SomeComponent {
    show(){
        console.log('show a2');
    }
    hide(){
        console.log('hide a2');
    }
}

let obj = new SpecializedComponent();
obj.show();

 

만약, 위와 같이 SomeComponent 클래스를 상속받은 SpecializedComponent 클래스가 show와 hide 메소드를 오버라이드했다고 가정하자.

 

class SomeComponent{
    // show(){
    //     console.log('show a1');
    // }
    // hide(){
    //     console.log('hide a1');
    // }
    setVisible(value: boolean){
        console.log('visible : ' + value);
    }
}

class SpecializedComponent extends SomeComponent {
    show(){
        console.log('show a2');
    }
    hide(){
        console.log('hide a2');
    }
}

let obj = new SpecializedComponent();
obj.show();
 
그리고 위와 같이 SomeComponent에서 show와 hide 메소드가 사라졌다 하더라도 SpecializedComponent에서는 일반 메소드 정의로 간주되어 오류가 발생하지 않는다.
이 문제를 해결하기 위해 타입스크립트 4.3에서는 오버라이드하는 메소드는 앞에 "override"라는 키워드를 붙여서 해당 메소드가 오버라이드라는 것을 명시하였다. 이를 통해, 추후 부모 클래스에서 해당 메소드가 삭제될 경우, 자식 클래스에서 오버라이드된 메소드들에 대해 오류가 발생하도록 한다.
 
class SomeComponent{
    show(){
        console.log('show a1');
    }
    // hide(){
    //     console.log('hide a1');
    // }
    setVisible(value: boolean){
        console.log('visible : ' + value);
    }
}

class SpecializedComponent extends SomeComponent {
    override show(){
        console.log('show a2');
    }
    override hide(){ //ERROR!
        console.log('hide a2');
    }
}

let obj = new SpecializedComponent();
obj.show();

템플릿 문자열 타입 개선

다음과 같이 템플릿 문자열을 통해 타입을 생성할 수 있다.

 

type Color = "red" | "blue";
type Quantity = "one" | "two";

/**
 * EXAMPLE: red fish / blue fish / one fish / two fish
 */
type SeussFish = `${Quantity | Color} fish`;

 

또는 다른 문자열을 대입해서 타입을 선언할 수 있다.

 

declare let s1: `${number}-${number}-${number}`;
declare let s2: `1-2-3`;

s1 = s2;

 

타입스크립트는 템플릿 문자열 타입을 추론할 수 있다.

 

function bar(s: string): `hello ${string}` {
    return `hello ${s}`;
}
console.log(bar('Mac')); //hello Mac

 

타입을 추론할 때도 사용되며, <extends string> 키워드를 사용하여 타입을 추론한다.

 

declare let str: string;
declare function f<T extends string>(x: T): T;

let x2 = f(`hello ${str}`);

 

타입스크립트는 다른 템플릿 문자열 타입 간에 더 좋은 관계를 추론한다.

 

declare let s1: `${number}-${number}-${number}`;
declare let s2: `1-2-3`;
declare let s3: `${number}-2-3`;

s1 = s2;
s1 = s3;

 

이전에는 s2에서 s1으로 매칭은 가능했지만, 조금더 복잡한 s3에서 s1으로의 매칭은 불가능했었다.
이제 타입스크립트는 s3에서 s1까지도 매칭이 가능하게 되었다.

ECMAScript #private 클래스 요소

#이름 이 런타임에서 완전히 private하게 작동되었다. 추가적으로, 메소드와 접근자에서도 private 명칭을 사용할 수 있게 되었다.

 

class Foo {
    #someMethod(){
        console.log('Hello World');
    }

    get #someValue(){
        return 100;
    }

    publicMethod(){
        this.#someMethod();
        return this.#someValue;
    }
}
new Foo().#someMethod(); //ERROR
new Foo().#someValue; //ERROR

ConstructorParameters를 추상클래스에서 사용

타입스크립트 4.3부터 추상 클래스에서 ConstructorParameters 타입이 동작하게 되었다.

 

abstract class C{
    constructor(a: string, b: number){}
}
//[a: string, b: number]
type CParams = ConstructorParameters<typeof C>;

 

항상 참인 Promise 검사

strictNullChecks 일때, Promise 가 참인지 여부 검사는 조건절에서 오류를 발생시킨다.

 

async function foo(): Promise<boolean>{
    return false;
}

async function bar(): Promise<string> {
    if(foo()){
        //오류 발생
        return "true";
    }
    return "false";
}

 

지금까지 인덱스 시그니처는 클래스의 객체 측면에서만 선언되었다. 이제 인덱스 시그니처는 static 에서 사용할 수 있다.

 

class Foo {
    static hello = "hello";
    static world = 1234;
    static [propName: string]: string | number | undefined;
}
Foo["whatever"] = 42; //OK
let x = Foo["something"]; //string | number | undefined

 

여기서, propName에 정의된 타입 외에는 static 멤버변수의 값을 정의할 수 없다.

 

class Foo {
    static hello = "hello";
    static world = 1234;
    static [propName: string]: string | number | undefined;
    static momo = true; //ERROR
}

 

Import 자동완성

모듈을 import할 때 일부만 입력해도 자동으로 추론하여 완성시키는 기능이 추가되었다.

편집기 지원 @link 태그

타입스크립트는 이제 @link 태그를 이해할 수 있다. 링크에 함수 이름을 넣으면 해당 함수에 대한 선언을 볼 수 있으며 Ctrl+클릭시 해당 함수로 이동한다.

 

function add(a: number, b: number){
    return a+b;
}
/**
 * {@link add} 참조
 */
function subtract(a: number, b: number){
    return a-b;
}

Enum과 임의의 값 비교 불가

절대 같을 수 없는 값을 비교하는 조건절은 오류를 발생시킨다.

 

enum E {
    A = 0,
    B = 1
}
function doSomething(x: E){
    if(x === -1){ //ERROR
        return true;
    }
    return false;
}

 

그러나, x의 타입을 E | -1 로 설정한다면 참을 반환할 수 있다.

 

enum E {
    A = 0,
    B = 1
}
function doSomething(x: E | -1){
    if(x === -1){ //OK
        return true;
    }
    return false;
}