Type Guards

kukudas·2022년 2월 9일
0

TypeScript

목록 보기
27/39

type guard는 조건문을 통해서 변수가 가질 수 있는 타입의 개수를 줄여나가게 해줌.

typeof

type alphanumeric = string | number;

function add(a: alphanumeric, b: alphanumeric) {
    if (typeof a === 'number' && typeof b === 'number') {
        return a + b;
    }

    if (typeof a === 'string' && typeof b === 'string') {
        return a.concat(b);
    }

    throw new Error('Invalid arguments. Both arguments must be either numbers or strings.');
}

위 코드에서 2개의 인자가 모두 number 혹은 string인지 확인하고 각각에 맞는 리턴을 해줌. 만약에 2개의 인자가 모두 number, string이 아닌경우에는 에러나오게함.
typeof를 통해서 인자의 타입을 알아낼 수 있음.

instanceof

class Customer {
    isCreditAllowed(): boolean {
        // ...
        return true;
    }
}

class Supplier {
    isInShortList(): boolean {
        // ...
        return true;
    }
}

type BusinessPartner = Customer | Supplier;

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    }

    if (partner instanceof Supplier) {
        message = partner.isInShortList() ? 'Sign a new contract the supplier' : 'Need to evaluate further';
    }

    return message;
}

let customer = new Customer();
let supplier = new Supplier();
console.log(signContract(customer));
console.log(signContract(supplier));

// Output :
Sign a new contract with the customer
Sign a new contract the supplier

위에서 BusinessPartner를 parameter로 받는 signContract() 함수를 만들고, 인자로 각각의 인스턴스를 넣었을때 instanceof로 인스턴스인지 아닌지 알 수 있음.

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }
    return message;
}

위 처럼 if...else로 해도 else를 탔을때 Customer의 인스턴스가 아닐 경우에 Customer의 인스턴스가 아닌 모든 것이 아닌 Supplier의 인스턴스여서 else를 타는것.

in

in으로 객체안에 property가 있는지 확인 가능함.

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if ('isCreditAllowed' in partner) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract the supplier ' : 'Need to evaluate further';
    }
    return message;
}

User-defined Type Guards

사용자 지정 타입 가드는 타입 가드를 정하거나 함수를 사용할때 타입스크립트가 타입을 추론하는데 도움을ㅈ 줌.
사용자 지정 타입 가드 함수는 단순히 arge is aType을 리턴하는 함수임.

function isCustomer(partner: any): partner is Customer {
    return partner instanceof Customer;
}

function signContract(partner: BusinessPartner): string {
    let message: string;
    if (isCustomer(partner)) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }

    return message;
}

위에서 isCustomer()는 사용자 지정 타입 가드 함수임.

is

boolean대신에 is를 사용하면 아래에서 isString()true를 리턴했을때 타입스크립트가 타입 가드가 블럭인 if문 안에서 foo의 타입을 string으로 생각함.
예시1은 컴파일 에러도 없고 런타임 에러도 없음.

// 예시 1
function isString(test: any): test is string{
    return typeof test === "string";
}

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length); // string function
    }
}
example("hello world");

예시2는 컴파일에러와 런타임에러를 가짐. 타입스크립트가 타입을 string으로 좁혔으므로 toExponetialstring에 속하는 메소드가 아니기 때문임.

// 예시 2
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}

예시 3은 컴파일 에러는 없지만 런타임에러는 생김. 타입스크립트가 if문 안의 타입만 string으로 좁혔기 때문에 foo.toExponential에서의 foo는 타입스크립트가 string이라고 생각하지 않으므로 컴파일에러가 발생하지는 않지만 저 메소드는 string의 메소드가 아니기 때문에 런타임에러가 생김.

// 예시 3
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
    }
    console.log(foo.toExponential(2));
}

예시 4처럼 test is string(type predicate)를 사용하지 않고 boolean을 사용하면 타입스트립트는 타입 가드된 블록에서 type narrow를 하지 않기 때문에 컴파일에러는 없지만 런타임에러가 나옴.

// 예시 4
function isString(test: any): boolean{
    return typeof test === "string";
}
function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        console.log(foo.toExponential(2));
    }
}
  • 타입가드는 조건문들 통해서 변수가 가지는 타입을 줄여나감
  • typeofinstanceof 연산자로 조건문에서 타입 가드를 구현가능함

출처1
출처2

0개의 댓글

관련 채용 정보