코딩쌀롱
[TS] 타입스크립트 메모2 본문
📌 인터페이스
1. 함수의 인자를 정의하는 인터페이스 (매개변수-인자, 반환값)
2. 함수 구조를 정의하는 인터페이스
// 함수의 스펙(구조)에 인터페이스를 활용
interface SumFunction {
(a: nubmer, b: number): number;
}
var sum: SumFunction;
sum = function(a: number, b: number): number {
return a + b;
}
3. 인덱싱 방식을 정의하는 인터페이스
// 인덱싱
interface StringArray {
[index: number]: string;
}
var arr: StringArray = ['a', 'b', 'c'];
arr[0] = 10; // 에러
4. 인터페이스 딕셔너리 패턴
// 딕셔너리 패턴
interface StringRegexpDictionary {
[key: string]: RegExp;
}
var obj: StringRegexpDictionary = {
sth: /abc/,
cssFile: 'css', // ❌ value가 정규표현식이 아니기 때문
jsFile: /\.js$/, // ⭕️
}
5. 인터페이스 확장(상속)
// 인터페이스 확장
interface Person {
name: string;
age: number;
}
interface Developer extends Person{
language: string;
}
const capt: Developer = {
language: 'ts',
age: 100,
name: '캡틴'
}
📌 타입 별칭(Type Aliases)
1. Type Aliases: 특정 타입이나 인터페이스를 참조할 수 있는 타입 변수.
타입 별칭은 새로운 값을 하나 생성하는 것이 아니라 정의한 타입에 대해 나중에 쉽게 참고할 수 있게 이름을 부여하는 것과 같다.
type Person = {
name: string;
age: number;
}
const seho: Person ={
name: '세호',
age: 30
}
// 타입 변수처럼 사용
type MyString = string;
const str: MyString = 'hello';
type Todo = { id: string; title: string; done: boolean};
function getTodo(todo: Todo) {
}
2. type vs interface: 타입의 확장 가능 / 불가능 여부. 인터페이스는 확장이 가능한데 반해 타입은 확장이 불가능하다. 따라서 type 보다는 interfac로 선언해서 사용하는 것을 추천한다.
📌 연산자 이용한 타입 정의
1. 유니온 타입 장점: 파이프 기호(|)로 하나의 타입 이상을 쓸 수 있게 해 줌.
any와 다르게 타입스크립트가 타입추론이 가능하다.
function logMessage(value: string | number) {
if(typeof value === 'number') { // 타입 가드
value.toLocaleString();
}
if(typeof value === 'string') {
value.toString();
}
}
logMessage('hello');
logMessage(100);
2. 유니온 타입 특징: 타입스크립트 입장에서 someone 매개변수가 Developer일지, Person일지 알 수 없기 때문에, someone.skill, someone.age를 타입 검증없이 사용할 수 없다! 그래서 에러 발생. 해결하기 위해 타입가드를 사용할 수 있다. 유니온 타입의 공통된 보장된 속성만 사용 가능하다.
interface Developter {
name: string;
skill: string;
}
interface Person {
name: string;
age: nubmer;
}
// 유니온 타입(|)
function askSomeone(someone: Developer | Person) {
someone.name
someone.skill // 에러
someone.age // 에러
}
3. 인터섹션 타입: 매개변수 someone은 Developer가 갖고 있는 name, skill, Person이 갖고 있는 name, age를 모두 포함한 3개의 속성을 갖는 타입이라는 뜻. 유니온 타입과 다르게 타입가드가 필요하지 않다. 실제로는 유니온타입을 더 많이 사용한다.
interface Developter {
name: string;
skill: string;
}
interface Person {
name: string;
age: nubmer;
}
// 인터섹션 타입 (&)
function askSomeone(someone: Developer & Person) {
someone.name
someone.skill
someone.age
}
4. 유니온 타입과 인터섹션 타입의 차이: 유니온 타입은 타입가드를 통해 타입추론을 해야 됨. 대신 넘겨주는 인자에 대해서 선택지가 생김. 반대로 인터섹션 타입은 두 개의 타입의 합집합인 새로운 타입을 만든 것.
📌 이넘(Enums)
1. 이넘: 이넘은 특정 값들의 집합을 의미하는 자료형
2. 숫자형 이넘
enum Shoes {
Nike,
Adidas
}
const myShoes = Shoes.Nike;
console.log(myShoes); // 0
3. 문자형 이넘
enum Shoes {
Nike = '나이키',
Adidas = '아디다스'
}
const myShoes = Shoes.Nike;
console.log(myShoes); // '나이키'
4. 이넘 활용: 드롭다운 등의 목록이 필요할 때 이넘을 쓰는 것이 정확한 코드를 쓸 수 있고, 예외처리 케이스 줄일 수 있다.
enum Answer {
Yes = 'Y',
No = 'N',
}
function askQuestion(answer: string) {
if(answer === Answer.Yes) console.log('정답')
if(answer === Answer.No) console.log('오답')
}
askQuestion(Answer.Yes);
askQuestion('Yes'); // 에러(인자 타입이 이넘이기 떄문에 이넘만 가능)
// askQuestion('예스');
// askQuestion('y');
// askQuestion('Yes');
📌 타입스크립트의 클래스
1. 클래스 최상단에 멤버 변수를 정의해줘야 함.
2. 멤버 변수의 유효 범위 지정 가능(private, public)
3. readonly 접근만 가능하고 변경 불가
3. constructor 매개변수에도 타입 지정.
class Person {
private name: stirng;
public age: number;
readonly log: string;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
📌 제네릭(Generics)
1. 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징. 여러 타입에서 동작하는 컴포넌트를 생성할 때 사용.
function logText<T>(text: T):T {
console.log(text);
return text;
}
logText<string>('하이');
2. 기존 타입 정의 방식과 제네릭의 차이점 - 함수 중복 선언의 단점
제네릭이 아닌 기존 타입 정의 방식을 사용하면 코드가 똑같음에도 타입에 따라 함수를 중복 선언해야한다는 단점이 있다.
3. 기존 문법과 제네릭의 차이점 - 유니온 타입을 이용한 선언 방식의 문제점
인풋에 대해서는 해결이 됐지만 반환값에 있어서는 해결이 되지 않음. 인자로 string을 넘겼지만 반환값의 타입은 string | number로 돼있음. 그래서 자동완성도 string, number의 교집합만 가능하다. 그래서 string을 인자로 줬어도 string 메서드를 쓰면 에러가 발생한다.
function logText(text: string | number) {
console.log(text);
return text;
}
const a = logText('a');
a.split('') // 에러 발생
// 타입이 string | number이기 때문에 타입스크립트는 string이라고 확신할 수 없음
logText(10);
4. 제네릭의 장점과 타입 추론에서의 이점
함수를 정의할 때 타입을 비워놓은 상태, 호출할 때 타입을 지정.
interface Dropdown<T> {
value: T;
selected: boolean;
}
const obj: Dropdown<number> = { value: 10, selected: false };
interface DropdownItem<T> {
value: T;
selected: boolean;
}
const emails: DropdownItem<string>[] = [
{ value: 'naver.com', selected: true },
{ value: 'gmail.com', selected: false }
];
const numberOfProducts: DropdownItem<number>[] = [
{ value: 1, selected: true },
{ value: 2, selectred: false }
];
function createDropdownItem<T>(item: DropdownItem<T>) {
...
}
emails.forEach(email => {
const item = createDropdownItem<string>(emails);
...
})
5. 제네릭 타입 제한1: 추가적인 타입 힌트주기
function logTextLength<T>(text: T): T {
console.log(text.length); // 에러! T가 뭔지 알 수 없기 때문에 length 속성이 있는지 알 수 없음.
return text;
}
logTextLength<string>('hi');
// 제네릭의 타입 제한 → 배열이라는 힌트를 주고 length 속성 사용 가능
function logTextLength<T>(text: T[]): T[] {
console.log(text.length);
return text;
}
logTextLength<string>(['hi', 'eve']);
6. 제네릭 타입 제한2: 정의된 타입 이용하기
// 제네릭 타입 제한2: 정의된 타입 이용
interface LengthType {
length: number;
}
function logTextLength<T extends LengthType>(text: T): T {
text.length;
return text;
}
logTextLength(10); // 에러! length 속성이 없기 때문
logTextLength({ length: 10 }); // OK! length 속성이 있는 객체기 때문
7. 제네릭 타입 제한3: keyof
ShoppingItem에 있는 key들 중에 한 가지가 제네릭T가 된다. → 'name', 'price', 'stock'
// 제네릭 타입 제한3: keyof
interface ShoppingItem {
name: string;
price: number;
stock: number;
}
function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T {
return itemOption;
}
getShoppingItemOption('name');
참고📚
인프런 - 캡틴판교 타입스크립트 입문 강의
'개발공부' 카테고리의 다른 글
[HTML¦CSS] multi range slider (0) | 2021.06.01 |
---|---|
react와 TypeScript로 canvas 그리기 (0) | 2021.05.31 |
[TS] 타입스크립트 메모_땅콩코딩 (0) | 2021.05.19 |
[LeetCode_JS] 70. Climbing Stairs _DP 기본✨ (0) | 2021.05.11 |