et cetera/TIL

타입스크립트 강의 내용 정리 (1)

iborymagic 2021. 12. 22. 03:35
반응형

옵셔널 파라미터

해당 파라미터는 포함해도되고 포함하지 않아도 된다.

function log(a: string, b?: string) {}

Type Aliases vs. Interface

1. 타입 별칭은 새로운 타입 값을 하나 생성하는 것이 아니라 

이미 정의한 타입에 대해 나중에 쉽게 참고할 수 있게 이름을 부여하는 것과 같다. 

2. 가장 큰 차이점은 확장 가능 여부. 타입은 확장이 불가능하다.
따라서 가능한 한 type보다는 interface로 선언해서 사용하는 것을 추천.

 

타입 가드

특정 타입으로 타입의 범위를 좁혀나가는(필터링하는) 과정

function logMessage(value: string | number) {
	if (typeof value === 'number') {
		// 이 if문 안에서는 value의 타입이 number로 추론된다.
		value.toLocaleString();
	}
	if (typeof value === 'string') {
		// 여기서는 value가 string으로 추론된다.
		value.toLocaleUpperCase();
	}
}

union type

interface Developer {
	name: string;
	skill: string;
}

interface Person {
	name: string;
	age: number;
}

function askSomeone(someone: Developer | Person) {
	someone.skill // X
	someone.name // O
}

someone은 Developer도 될 수 있고 Person도 될 수 있다.
타입스크립트의 관점에서는 someone이 둘 중 어떤 타입이 될지 모르기때문에
Developer의 skill이라던가 Person의 age를 타입 검증도 없이 바로 쓰게 되면
그 코드는 type safe 하지 않은, 즉 에러가 충분히 발생할 수 있는 코드라고 판단한다.


만약 someone.skill이나 someone.age를 쓰고 싶다면 타입 가드를 통해 둘 중 하나의 타입으로 제한해줘야 함.

 

union type과 intersection type의 호출 시 차이점

// union type
function askSomeone(someone: Developer | Person) {
	// ...
}
askSomeone({ name: '개발자', skill: '웹 개발' });
askSomeone({ name: '사람', age: 100 });

// intersection type
function askSomeone(someone: Developer & Person) {
	// ...
}
askSomeone({ name: '개발자', skill: '웹 개발', age: 100 });

union 타입인 someone은 말 그대로 Developer 아니면 Person 이므로 인자로 둘 중 하나가 들어가면 된다.

반면, intersection 타입인 someone은 Developer 이면서 Person 이어야하므로,

둘의 속성을 모두 가지는 객체를 인자로 집어넣어야한다.

 

숫자형 enum

enum Shoes {
  Nike, // 0
  Adidas // 1
}

const myShoes = Shoes.Nike;
console.log(myShoes); // 0
// enum에 별도의 값을 지정하지 않으면 숫자형 enum으로 취급

enum Shoes {
  Nike = 10, // 10
  Adidas, // 11
  NewBalance // 12
}
// 처음 지정한 숫자로부터 1씩 증가하는 형태

문자형 enum

enum Shoes {
  Nike = '나이키',
  Adidas = '아디다스'
}

const myShoes = Shoes.Nike;
console.log(myShoes); // '나이키'

enum 사용 예시

// enum 사용 전
function askQuestion(answer: string) {
	if (answer === 'yes') {
		console.log('정답입니다');
	}
	if (answer === 'no') {
		console.log('오답입니다');
	}
}
askQuestion('예스');
askQuestion('y');
askQuestion('Yes');

// enum 사용 후
// 예외 처리의 케이스를 많이 줄일 수 있다.
enum Answer {
	Yes = 'Y',
	No = 'N'
}

function askQuestion(answer: Answer) {
	if (answer === Answer.Yes) {
		console.log('정답입니다');
	}
	if (answer === Answer.No) {
		console.log('오답입니다');
	}
}
askQuestion(Answer.Yes); // O
askQuestion('Yes'); // X
// enum으로 정의했으므로, enum에서 제공하는 데이터만 넣을 수 있다.

 몰랐던 Interface 사용 예시

// 함수의 스펙(구조)에 인터페이스를 활용
interface SumFunction {
    (a: number, b: number): number;
}

const sum:SumFunction = function(a: number, b: number): number {
  return a + b;
}

// 인덱싱 방식을 정의하는 인터페이스
interface StringArray {
  [index: number]: string;
}

const arr: StringArray = ['a', 'b', 'c'];
arr[0]; // 'a'

// 딕셔너리 패턴
interface StringRegexDictionary {
  [key: string]: RegExp;
}

const obj: StringRegexDictionary = {
  cssFile: /\.css$/,
  jsFile: /\.js$/,
}

obj.cssFile = 'a'; // X. RegExp 타입이 들어가야 함.
반응형