➕ 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>, 이렇게 기본값 넣어줌