일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 프로그래머스
- 리트코드
- 리액트
- 코어 자바스크립트
- Async
- 2주 프로젝트
- 제로초
- 4주 프로젝트
- 파이썬
- 자바스크립트
- programmers
- 타임어택
- SQL 고득점 Kit
- 타입스크립트 올인원
- 렛츠기릿 자바스크립트
- 백준
- 토익
- 정재남
- python
- 회고
- til
- javascript
- 손에 익히며 배우는 네트워크 첫걸음
- 코드스테이츠
- codestates
- js
- 리덕스
- 알고리즘
- LeetCode
- 타입스크립트
- Today
- Total
Jerry
[TIL] [타임어택9기][리뉴얼] 타입스크립트 올인원 : Part1. 기본 문법편 - (5) : 원시 래퍼 타입, 템플릿 리터럴 타입, rest 튜플 / enum, keyof, typeof / union(|)과 intersection(&) / 타입 애일리어스와 인터페이.. 본문
[TIL] [타임어택9기][리뉴얼] 타입스크립트 올인원 : Part1. 기본 문법편 - (5) : 원시 래퍼 타입, 템플릿 리터럴 타입, rest 튜플 / enum, keyof, typeof / union(|)과 intersection(&) / 타입 애일리어스와 인터페이..
juicyjerry 2024. 2. 27. 00:31섹션 1 기본 문법 배우기
<원시 래퍼 타입, 템플릿 리터럴 타입, rest 튜플>
원시 래퍼 타입
const a: string = 'hello';
const b: String = 'hello';
a와 b는 서로 다른 타입이다.
b는 랩퍼 객체로, new String(); 이런 식으로 사용하는 객체이며, 평소에 잘 사용하지 않는다.
그러니, 대소문자 구분을 잘하자.
참고로, 타입스크립트는 자동 완성 추천 기능도 제공 ( ctrl + space )
템플릿 리터럴 활용
type World = "world" | "hell";
const c: World = 'world';
const d = `hello ${c}`;
type Greeting = `hello ${World}`;
rest parameter 활용
let arr: string[] = [];
let arr2: Array<string> = [];
function rest(a, ...args: string[]) {
console.log(args); // 1, 2, 3
}
rest('1', '2', '3');
튜플 활용
const tuple: [string, number] = ['1', 1];
tuple[2] = 'hello';
tuple.push('hello');
타입스크립트가 "tuple[2] = 'hello';" 는 막지만, "tuple.push('hello');"는 막지 못 하는 단점이 존재
<enum, keyof, typeof>
enum 타입 : 보통 변수들을 하나의 그룹으로 묶고 싶을 때 사용
const enum EDirection {
Up = 3,
Down = 5,
Left = 1,
Right = 0,
}
as const 는 js로 변환 시 남아있다
남아있게 하고 싶으면 객체, 아니면 enum, 모르겠으면 남겨라
만약, 타입스크립트가 바보같이 행동하면 직접 나서야 한다.
const f = EDirection.Up;
const g = EDirection.Down;
const ODirection = {
Up : 3,
Down : 5,
Left : 1,
Right : 0,
} as const;
실제 enum 쓰는 코드
function walk(dir: EDirection) {}
// enum 쓰기 싫다, #4처럼 해야 되는데 타입 정의가 복잡해진다
type Direction = typeof ODirection[keyof typeof ODirection];
function run(dir: EDirection) {} // dir은 네 개중에 하나여야 한다라는 뜻
walk(EDirection.Left);
run(ODirection.Right);
keyof에 대해서
const obj = { a: '123', b: 'hello', c: 'world'} as const; // as const 아주 엄격하게 타입핑해준다
type Key = keyof typeof obj; // key들만 가져오고 싶을 경우
type Key = typeof obj[keyof typeof obj]; // value들만 가져오고 싶을 경우
<union(|)과 intersection(&)>
둘 중에 뭐가 낫냐
간단하게 하려면 타입, 객체지향 프로그래밍하고 싶을 때 interface
type A = {a: string};
const a: A = {a: 'hello'};
const a: {a: string} = {A: 'hello'};
interface B { a: string};
const b: B = { a: 'hello'};
union : 모든 경우의 수를 고려한다
function add(x: string | number, y: string | number): string | number {return x + y};
const result: string | number = add(1, 2);
add(1, 2);
add('1', '2');
add(1, '2');
위 add 함수 타입은 잘못되었다.
왜냐하면 add 함수 타입을 허용하면 다음 예시(result)부터 꼬인다
add(1, 2)의 결과가 숫자인데, 타입이 string이 될 수 있는 잘못된 상황이 나타나게 된다
처음 타입 정의를 잘 해야 한다, 안 그러면 줄줄이 꼬인다
type A 코드 상, string이면서 numnber여야 한다 (X) ; 논리적으로 말이 안 됨
그럼 언제 앰퍼샌드(&)를 사용하는가? ===> 객체
type A = string & number;
type D = { hello: 'world' } & { zero: 'cho' }; // 모든 속성이 있어야 한다 (인터섹션)
const k: D = { hello: 'world', zero: 'cho'};
type F = { hello: 'world' } | { zero: 'cho' }; // 여러개 중에 하나만 있어도 된다 (유니온)
const t: D = { hello: 'world'};
<타입 애일리어스와 인터페이스의 상속(extends)>
상속의 예제
type Animal = { breath: true };
type Mammal = Animal & { breed: true };
type Human = Mammal & { think: true };
const zerocho: Human = { breath: true, breed: true, think: true };
interface A {
breath: true
}
interface B extends A {
breed: true
}
const b: B = { breath: true, breed: true };
둘 중에 뭘 사용할지 선택하기만 된
간단 - type, 객체지향 - interface
interface A {
talk: () => void;
}
interface A {
eat: () => void;
}
interface A {
shit: () => void;
}
// 보통 라이브러리들은 인터페이스로 , 확장이 가능하다, 서로간에 합쳐질 수 있다
const a : A = { talk() {}, eat() {}, shit() {}, sleep() {} }
interface A {
sleep: () => void;
}
네이밍
interface IProps {}
type TAlias = string | number;
enum EHello {
Left,
Right
}
옛날 트렌드로는 각 타입 첫 글자 대문자를 붙여주었지만, 요즘은 제너릭에만 붙인다고 한다.
<타입을 집합으로 생각하자(좁은 타입과 넓은 타입)>
type A = string | number;
type B = string;
넓은 타입에서 좁은 타입으로 대입 불가능, 그 반대는 가능
비슷한 원리로 any는 전체 집합, never는 공집합으로 볼 수 있어요
객체의 경우는 좀 다르다
속성이 적을수록 넓은 타입, 속성이 많을수록(상세, 구체적일수록) 좁다
type A = {name: string};
type B = {name: number};
type C = {name: string, age: number};
좁은 타입, 넓은 타입 검사할 때,
객체리터럴을 바로 집어넣으면 잉여속성 검사라는 게 등장하여 안 되는 경우가 발생할 수 있다.
type A = {name: string};
type B = {name: number};
type AB = A | B;
TYPE C = A & B;
const ab: AB = { name: 'zerocho'};
const c: C = { name: 'zerocho', age: 29, married: false };
// married: false 잉여속성검사 걸림
// 그래서 따로 변수로 빼서 할당해주면 안 걸림
const obj = { name: 'zerocho', age: 29, married: false }
const c: C = obj;
다음 내용(next)
void의 두 가지 사용법 unknown과 any(그리고 타입 대입가능표) 타입 좁히기(타입 가드) 커스텀 타입 가드(is, 형식 조건자) {}와 Object readonly, 인덱스드 시그니처, 맵드 타입스 클래스의 새로운 기능들 옵셔널, 제네릭 기본 기본값 타이핑 섹션 2 lib.es5.d.ts 분석 - forEach, map 제네릭 분석