
➕ zerocho님 typescript all-in-one 강의를 듣고 정리한 내용입니다.
// interface끼리는 서로 합쳐짐
interface A { a: string }
interface A { b: string }
const obj1: A = { a: 'hello', b: 'world' }
// Type Alias끼리는 서로 합쳐지지 않고 에러남
type B = { a: string }
type B = { b: string }
const obj2: B = { a: 'hello', b: 'world' } // error
Type Alias는 intersection으로 상속, interface는 extends로 상속
객체 리터럴은 잉여 속성 검사가 있음.

중간에 다른 변수를 하나 껴서 넣으면 에러가 나지 않음

따라서 ts에서 객체 리터럴을 바로 대입하려면 잉여속성검사를 해야한다!
type A = { hello: string };
const a: A = { hello: 'world', why: 'error' }; // why가 없다고 error
const b = { hello: 'world', why: 'error' }; // 잉여 속성 검사
const c: A = b;

a와 b의 리턴값이 모두 void
return 값이 void로 function을 선언한 것(return 값 없음)과 메소드로 선언한 void, 매개변수로 선언한 void(return 값 존재가능)는 다르다
전자는 return값이 없다 후자는 return값을 사용하지 않겠다를 의미한다. 하지만 후자에 경우 return type을 void로 받기에 a.talk의 return 값이 3임에도 type을 void로 인식하는 문제가 발생한다! (이럴 경우 number로 다시 강제 타입 변환 as unknown as number )
function hello() : void{ // 함수 return값 void
}
interface A {
talk: () => void; // 메서드 void
}
const a: A = {
talk() { return 3; }
}
function a(callback : () => void) : void{ // 매개변수 void
}
declare을 붙이면 type만 지정할 수 있음( 구현은 다른 파일에 있어야함 ) , js변환시 사라짐
declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;
let target: number[] = [];
forEach([1, 2, 3], el => target.push(el));

//push는 return 값이 number여서 undefined 하면 error
declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
forEach([1, 2, 3], el => target.push(el)); // return type number
forEach([1, 2, 3], el => {target.push(el)}); // return type void
// push return값 number인데 void해도 error 안나는 이유는 매개변수에서 void는 실제 return값이 무엇이든 상관하지 않아서
any : 타입검사 안할꺼야~ (포기)
unknown : 지금 당장은 잘 모르겠고 나중에 쓸 때 지정해서 쓸거야~

// unknown error 종류
error as Error
error as AxiosError

[해석방법]
any는 void에 대입 가능하다.
null은 void에 대입 불가능하다.
빈 배열 = never 이기에 never안뜨게 빈 배열일때 type지정 잘 하기!
초록색 ✔표시도 ❌
function numOrStr(a: number | string) { // 매개변수로 number 혹은 string
if (typeof a === 'string') { // a의 type 좁히기, string일 때
a.split(',');
} else { // type이 number일때만 toFixed() 사용 가능
a.toFixed(1);
}
}
function numOrNumArr(a: number | number[]) {
if (Array.isArray(a)) { // number[] 일때 ( 배열인지 아닌지 )
a.slice(1);
} else {
a.toFixed(1);
}
}
class A{
aaa() {}
}
class B{
bbb() {}
}
function aOrB( param : A | b){
if(param instanceof A){
param.aaa();
}else{
param.bbb();
}
}
aOrB(new A()) // ⭕ (인스턴스)
aOrB(b) // ❌
type B = { type: 'b', bbb: string };
type C = { type: 'c', ccc: string };
type D = { type: 'd', ddd: string };
type A = B | C | D;
// 객체들간의 값(type)으로 검사 -> 객체들간의 태그, 라벨을 달아준다!
function typeCheck(a: A) {
if (a.type === 'b') { // type B = { type: 'b', bbb: string };
a.bbb;
} else if (a.type === 'c') { // type C = { type: 'c', ccc: string };
a.ccc;
} else { // type D = { type: 'd', ddd: string };
a.ddd;
}
}
// 객체들간의 속성으로 검사
function typeCheck(a: A) {
if ('bbb' in a) { // type B = { type: 'b', bbb: string };
a.bbb;
} else if ('ccc' in a) { // type C = { type: 'c', ccc: string };
a.ccc;
} else { // type D = { type: 'd', ddd: string };
a.ddd;
}
}
is : 타입을 구분해주는 타입 가드를 커스텀 함수로 만들 수 있음
interface Cat { meow: number }
interface Dog { bow: number }
function catOrDog(a: Cat | Dog): a is Dog {
// 타입 판별을 직접 만들기
if ((a as Cat).meow) { return false } // a는 Dog 이기에 a가 Cat 이면 false
return true;
}
function pet(a : Cat | Dog){
if (catOrDog(a)) { // a:Dog
console.log(a.bow);
}
// 간단하게 하려면 이렇게도 가능함
if ('meow' in cat) {
console.log(cat.meow);
}
}
// PromiseSettledResult : 완료된 것
// PromiseRejectedResult : 완료된 것들 중 실패한 것
// PromiseFulfilledResult : 완료된 것들 중 성공한 것
const isRejected = (input: PromiseSettledResult<unknown>): input is PromiseRejectedResult => {
input.status === 'rejected';
}
const isFulfilled = <T>(input: PromiseSettledResult<T>): input is PromiseFulfilledResult<T> => {
input.status === 'fulfilled';
}
const promises = await Promise.allSettled([Promise.resolve('a'), Promise.resolve('b')]);
const errors = promises.filter(isRejected); //에러들
const fulfills = promises.filter(isFulfilled); //성공들
ts 4.8 버전 업데이트와 관련된 내용
//ver 4.8
const x : {} = "hello";
const y : Object = "hi";
const xx : object = "hi"; // 객체
const yy : object = {hello : "world"}; // 하지만 객체 할때는 object 지양, interface, type, class 지향
const z : unknown = "hi"; // unknown은 모든 값을 다 받을 수 있음
// unknown = {} : null | undefined
if (x){ // type unknown
x; // type {} (모든타입)
}
interface A {
readonly a: string;
b: string;
}
//type A = {a: string, b: string, c: string, d: string};
type A = {[key: string] : string} // 어떤 key 든 간에 문자열, 값도 문자열
type B = "Human" | "Mammal" | "Animal" ;
type A = {[key in B] : string} // key 가 B 중에 하나
클래스 이름이 타입이 될 수 있다. ( new A )
interface A {
readonly a : string;
b:string;
}
class B implements A { // 클래스는 인터페이스를 따라야함
private a: string; // private ( 실제 코드에서는 public )
protected b: string; // protected
}
class C extends B {}
new C().a; // private라서 접근 불가
new C().b; // 상속받으면 접근 가능

abstract class X { // 추상
abstract work(user: User): boolean; // 추상 메소드
}
class Y extends X { // 구현
work(user: User): boolean { // 구현 메소드
return true;
}
}
const constructor: abstract new (...args: any) => any = ...
function abc(a: number, b?: number, c: number) {}
abc(1)
abc(1, 2)
abc(1, 2, 3)
function infinite(...args: number) {} // 갯수 제한없이
infinite(1,2,3,4,5,6,7)
let obj: { a: string, b?: string } = { a: 'hello', b: 'world' }
obj = { a: 'hello' };
function add(x: stirng|number, y: stirng|number): stirng|number {return x+y}; //❌
// 안되는 이유는 다음과 같은 결과를 기대했지만
add(1,2) // 3
add('1','2') //'12'
// 아래와 같은 경우가 발생할 수 있기 때문에
add(1,'2')
add('1',2)
따라서 첫번째 케이스만 발생하게 하기 위해서는 제너릭 이용!
같은 타입은 하나의 동일한 문자로 표기
function add<T>(x: T, y: T): T { return x + y }
add<number>(1, 2);
add(1, 2);
add<string>('1', '2');
add('1', '2'); //❌
add(1, '2'); //❌
function a<T>() {}
class B<T>() {}
interface C<T> {}
type D<T> = {};
const e = <T>() => {};
function add<T extends string>(x: T, y: T): T { return x + y } //T는 string만
add(1, 2);
add('1', '2')
// <T extends {...}> // 특정 객체
// <T extends any[]> // 모든 배열
// <T extends (...args: any) => any> // 모든 함수 (any: 제한없다)
// <T extends abstract new (...args: any) => any> // 생성자 타입
// <T extends keyof any> // string | number | symbol
기본값 설정하고, 타입 지정
const A = ( a: number = 3, b: number = 5) =>{
return '3'
}
const B = (b : (animal: string) = { animal : " cat"}) => {
}
react jsx에서는 <T>를 <div>랑 헷갈려해서 <T - unknown>, 이렇게 기본값 넣어줌