Typescript 공부하기 7일차 (2022.09.30)
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는 런타임에 객체의 프로퍼티를 알 수 없는 경우에만 사용해야 한다.