타입스크립트

Typescript 공부하기 7일차 (2022.09.30)

개발자A입니다 2022. 9. 30. 23:36

1. Optional Chaining

1) 특징

   - 접근하는 객체의 프로퍼티가 null 또는 undefined 일 수 있는 Optional property인 경우 if문을 사용하지 않고 넘어가게 하는 체이닝 방법

   - es2020에서 추가된 문법이며 객체가 null 또는 undefined를 리턴. 그렇지 않는 경우 데이터 값을 리턴

 

2) &&와 ?.의 차이점

   - &&: falsy(false, null, undefined, '', 0, -0, NaN) 값 체크

   - ?(Optional Chaining): null과 undefined만 체크

 

3) 활용

   - Object, Array

   - Optional Function

   - if문 줄이기 (가독성 향상)

type Tail = {
	살랑살랑: () => void;
};

type Human = {
	call: (dogName: string) => void;
};

type Dog = {
	name: string;
    tail?: Tail;
    주인?: Human;
};

// if 사용시
funcion petDog(dog: Dog) {
	if (dog.주인 != null) {
    	dog.주인.call(dog.name);
    }
	if (dog.tail != null) {
    	dog.tail.살랑살랑();
    }
}

// Optional Chaining 사용시
function petDog(dog: Dog) {
	dog.주인?.call(dog.name)
    dog.tail.살랑살랑();
}

 

 

 

2. Nullsh Coalescing Operator

1) 특징

   - A??B

   - 기존의 A||B는 A가 falsy한 값(0, '', -0. NaN)인 경우 B를 반환.

   - null, undefined를 제외한 falsy한 값을 그대로 리턴하고 싶은 경우 사용

   - es202에서 추가된 문법이며, 좌항이 null, undefined인 경우에만 B를 리턴

 

2) Default 값을 정의할 때, ||를 쓰는 경우와 ??를 쓰는 경우

   - A || B: 좌항이 null, undefined인 경우에 B를 리턴

   - A ?? B: 좌항이 null, undefined인 경우에 A를 리턴

// price가 0인 경우 -1 반환
function getPrice(product: { price?: number }) {
	return product.price || -1;
}

// price가 0인 경우 0 반환
function getPrice(product: { price?: number }) {
	return product.price ?? -1;
}

 

 

 

3. Function Overloading

1) 특징

   - 파라미터의 형태가 다양한 여러 케이스에 대응하는 같은 이름을 가진 함수를 만드는 것

   - 함수의 다형성(다양한 형태)을 지원하는 것

 

2) 사용되는 상황

   - 파라미터의 타입만 다르고 비슷한 코드가 반복되고 있는 상황

   - 코드의 중복을 줄이고 재사용성을 높이기 위해

 

3) 함수 오버로딩을 위해 해야하는 것

   - 선언: 함수가 어떤 파라피터 타입들을 다룰 것인지 선언

   - 구현: 각 파라미터 타입에 대응하는 구체적인 코드를 작성

 

4) 선언

   - 함수의 이름이 같아야 한다.

   - 매개변수의 순서는 서로 같아야 한다.

   - 반환 타입이 같아야 한다.

class User {
	constructor(private id: string) {}
    
    setId(id: string): string;
    setId(id: number): string;
}

 

5) 구현

class User {
	constructor(private id: string) {}
    
    // 매개변수의 개수가 같을 때
    setId(id: string): void;
    setId(id: number): void;
    setId(id: string | number): void {
    	this.id = typeof id === 'number' ? id.toString() : id;
    };
    
    // 매개변수의 개수가 다를 때
    setId(id: string): void;
    setId(id: number, radix: number): void;
    setId(id: string | number, radix?: number): void {
    	this.id = typeof id === 'number' ? id.toString(radix) : id;
    };
}

 

6) 제네릭과의 차이점

   - 타입을 추론할 수 있는 시점과 용도의 범위

   - 제네릭: 타입이 사용되는 시점에 추론

                  제네릭 타입, 인터페이스, 클래스, 함수, 메서드 등

   - 함수 오버로딩: 타입이 선언하는 시점에 추론

                  함수, 메서드

 

 

 

4. Type Assertion

1) 특징

   - 타입스크립트가 추론하지 못하는 타입을 as keyword를 통해 명시해주는 것

 

2) Type Casting과 Type Assertion의 차이

   - Type Casting: 데이터의 타입을 변환

   - Type Assertion: 데이터의 타입을 명시

 

3) 형태

let someValue: unkown = "this is a string";

// As 형태
let strLength: number = (someValue as string).length;

// 꺾쇠(Angle bracket)
let strLength: number = (<string>someValue).length;

   - 주의: react의 JSX에서는 꺾쇠괄호를 통한 Type Assertion은 태그와 혼동되기 때문에 잘 사용하지 않습니다. 

 

4) 선언과 단언

type Duck = {
	꽥꽥: () => void;
	헤엄: () => void;
};

// 1) 타입 단언
// 타입스크립가 개발자의 말만 믿고 Duck 타입으로 인식하여 빈 객체임에도 에러가 발생하지 않음
const duck = {} as Duck 

// 2) 타입 선언
// 객체 프로퍼티를 모두 채우도록 강제하기 때문에 실수가 발생할 위험이 낮음
const duck: Duck = {
	꽥꽥() {
    	console.log('꽥꽥');
    },
    헤엄() {
    	console.log('어푸어푸');
    },
};

 

5. Index Signature

1) 특징

   - JS의 정의: 객체의 특정 value에 접근할 때 그 value의 key를 문자열로 인덱싱해서 참고하는 방법 

   - TS의 정의: JS의 인덱스 시그니처에 대한 타입을 지정해주는 것

 

2) 사용하는 상황

   - 객체의 프로퍼티들을 명확히 알 수 없을 때

 

3) 문제점

    - empty object일 때 인덱스 시그니처로 참조하려해도 타입에러가 나지않음

   - key마다 다른 타입을 가질 수 없음

   - 타입에 유연함을 제공하는 대신 키 이름을 잘못 쓰는 휴먼 에러를 저리를 가능성이 있다.

   - 즉, 어떤 타입이 올지 알 수 있는 상황이라면 정확한 타입을 정의하여 실수를 방지하는 게 좋다.

   - Index signature는 런타임에 객체의 프로퍼티를 알 수 없는 경우에만 사용해야 한다.