일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- useAppDispatch
- CORS
- Jest
- Promise
- autosize
- 호이스팅
- SSR
- tailwind
- CI/CD
- async/await
- 태그된 유니온
- recoil
- 인터섹션
- 타입 좁히기
- RTK Query
- 반공변성
- 무한 스크롤
- map
- ESlint
- React
- dfs
- TS
- webpack
- 투포인터
- app router
- 이분 검색
- 결정 알고리즘
- 리터럴 타입
- Cypress
- 공변성
- Today
- Total
짧은코딩
TS 기본 기식(2) 본문
타입 가드
function numOrStr(a:number|string) {
a.toFixed(1);
}
numOrStr('123');
numOrStr(1);
이렇게 하면 ts는 모든 가능성을 열어두기 때문에 오류가 난다. 왜냐하면 toFixed는 number에서만 사용할 수 있기 때문이다.
toFixed는 매개변수 숫자만큼 소수점이 생긴다.
function numOrStr(a: number | string) {
if (typeof a === "number") {
a.toFixed(1);
} else {
a.charAt(3);
}
}
numOrStr("123");
numOrStr(1);
따라서 이렇게 표시하면 number인 것이 확실해서 오류가 발생하지 않는다. 그리고 else 문으로 가면 string인 것을 안다.
Class
class A {
aaa() {}
}
class B {
bbb() {}
}
function aOrB(param: A | B) {
if (param instanceof A) {
param.aaa();
}
}
aOrB(new A());
aOrB(new B());
클래스는 이름 자체를 타입 부분에 사용할 수 있다. 그리고 만드시 new를 붙여야한다.
if문으로 객체 구별
-type로 구분하는 법
type B = { type: "b"; bbb: string };
type C = { type: "c"; ccc: string };
type D = { type: "d"; ddd: string };
function typeCheck(a: B | C | D) {
if (a.type === "b") {
a.bbb;
} else if (a.type === "c") {
a.ccc;
} else {
a.ddd;
}
}
if 문에서도 타입 추론을 해준다. 안에 속성으로 타입 추론을 해준다.
-속성으로 구분하는 법
type B = { type: "b"; bbb: string };
type C = { type: "c"; ccc: string };
type D = { type: "d"; ddd: string };
function typeCheck(a: B | C | D) {
if ("bbb" in a) {
a.bbb;
} else if ("ccc" in a) {
a.ccc;
} else {
a.ddd;
}
}
이렇게 in 연산자를 활용하면 된다.
=> 나중에 코딩할 때 객체 안에다가 습관적으로 type을 달아주는 것이 좋다. 이로 구별을 할 수 있다. 이를 태그를 달아준다고 한다.
타입을 구분해주는 커스텀 함수
interface Cat {
meow: number;
}
interface Dog {
bow: number;
}
function catOrDog(a: Cat | Dog): a is Dog {
if ((a as Cat).meow) {
return false;
}
return true;
}
function pet(a: Cat | Dog) {
if (catOrDog(a)) {
console.log(a.bow);
}
if ("meow" in a) {
console.log(a.meow);
}
}
이렇게 CatOrDog 함수를 통해서 Dog인지 Cat인지 구분하는 함수를 만들고 구분할 수 있다.
is가 들어있는 함수는 커스텀 타입 가드 함수이다. 커스텀 타입 가드 함수는 if문 안에서 사용한다. 복잡해지면 사용하면 좋다.
Promise
Promise는 비동기이다.
Promise가 실행중인 상태에서는 Pending 상태 -> 실행이 끝나면 실패하든 성공하든 Settled 상태이며 Settled 안에 (Resolved, Rejected), 즉 (성공, 실패)가 있는 것
예를 들어 promise.then().catch() 이렇게 하는데 then과 catch가 settled이다. 그리고 then이 Resolved, catch가 Rejected라고 부르는 것이다.
-PromisesettledResult
PromisesettledResult 안에 PromiseRejectedResult(실패)와 PromiseFulfilledResult(성공) 이렇게 나눠진다.
-예시
const isRejected = (
input: PromiseSettledResult<unknown>
): input is PromiseRejectedResult => {
return input.status === "rejected";
};
const isFulfilled = <T>(
input: PromiseSettledResult<T>
): input is PromiseFulfilledResult<T> => {
return input.status === "fulfilled";
};
const promise = await Promise.allSettled([
Promise.resolve("a"),
Promise.resolve("b"),
]);
// 실패한 애들만 모아두는 코드, 하지만 타입이 settled
const errors = promise.filter((promise) => promise.status === "rejected");
// 실패한 애들만 모아두는 코드, 타입이 Rejected
const errors2 = promise.filter(isRejected);
export {};
errors의 filter 안에 있는 코드와 isRejected의 코드는 사실 같은 것이다. 하지만 최종적인 타입에 차이가 있다.
인덱스 시그니처
type A = { a: string; b: string; c: string };
type B = { [key: string]: string };
const aaaa: B = { a: "hello", b: "world" };
타입 A와 B는 같은 것이다. B는 모든 값의 속성이 string이길 원하면 사용하면 된다.
type B = "Human" | "Mammal" | "Animal";
type A = { [Key in B]: number };
const aaaa: A = { Human: 123, Mammal: 5, Animal: 7 };
혹은 이렇게 in을 사용해서 타입을 제한을 걸 수 있다. 이렇게 하면 최대한 정확하게 타입을 정해줄 수 있다.
type B = "Human" | "Mammal" | "Animal";
type A = { [Key in B]: B };
const aaaa: A = { Human: "Animal", Mammal: "Human", Animal: "Mammal" };
이렇게도 사용이 가능하다. interface에서는 '|'와 '&'가 안되기 때문에 type을 사용한다.
클래스
interface A {
readonly a: string;
b: string;
}
class B implements A {
private a: string = "123";
protected b: string = "world";
c: string = "wow";
method() {
console.log(this.a);
console.log(this.b);
console.log(this.c);
}
}
class C extends B {
method() {
console.log(this.a); //private이라 사용 불가
console.log(this.b); // protected고 B가 부모라서 사용 가능
console.log(this.c);
}
}
new C().a;
new C().b;
new C().c;
클래스의 모양을 interface로 통제할 수 있다. public, protected, private을 사용할 수 있다. JAVA와 굉장히 유사하다.
public | protected | private | |
클래스 내부 | O | O | O |
인스턴스 | O | X | X |
상속 클래스 | O | O | X |
=> 자바 원칙에 의해 interface로 추상적 구현을 해줘야 하지만 JS다 보니까 interface를 생략해도 상관은 없다.
-abstract
abstract class B implements A {
private a: string = "123";
protected b: string = "world";
c: string = "wow";
abstract method(): void;
}
class C extends B {
method() {
console.log(this.a); //private이라 사용 불가
console.log(this.b); // protected고 B가 부모라서 사용 가능
console.log(this.c);
}
}
new C().a;
new C().b;
new C().c;
abstract는 추상적으로만 만들어 두고 구현은 다른 곳에서 한다는 의미이다. 따라서 구현을 C 클래스에서 했다. abstract가 있는 것은 다른 클래스에서 반드시 구현해줘야 에러가 안난다.
=> 이런 abstract가 있기 때문에 interface를 잘 안쓴다.
옵셔널 체이닝
function abc(a: number, b?: number, c?: number) {}
abc(1);
abc(1, 2);
abc(1, 2, 3);
? 위치가 중요하다. ?가 붙어 있는 것은 있어도 되고 없어도 된다.
function abc(...args: number[]) {}
abc(1);
abc(1, 2);
abc(1, 2, 3);
혹은 이렇게 하면 개수 제한이 없다.
오버로딩
interface Add {
(x: number, y: number): number;
(x: string, y: string): string;
}
const add: Add = (x: any, y: any) => x + y;
class A {
add(x: number, y: number): number;
add(x: string, y: string): string;
add(x: any, y: any) {
return x + y;
}
}
const c = new A().add(1, 2);
이렇게 오버로딩이 가능하며 return하는 함수에서는 any를 사용해도 된다.
'TS > TS(with ZeroCho)' 카테고리의 다른 글
TS와 건망증 (0) | 2022.08.20 |
---|---|
리턴값, 매개변수의 대입 범위 (0) | 2022.08.20 |
타입을 만드는 법 (0) | 2022.08.20 |
제네릭 (0) | 2022.08.18 |
TS 기본 지식 (0) | 2022.08.11 |