:
ex) const name: string = "Mark";
type
ex) type Add = () => number;
interface
ex) interface Minus {}
제네릭
ex) Array<string>
type tuple: [string, number] = [ '1', 1 ];
// 둘 다 세번째 요소를 추가하는 코드이지만 push메서드를 에러를 발생시키지 않음
tuple[2] = 2 // ❌ error
tuple.push(2) // 👌
=
을 사용하여 값 지정 가능(문자열도 가능)const enum EDirection {
UP,
DOWN,
LEFT,
RIGHT
}
function walk(dir: EDirection ){console.log(dir)}
walk(EDirection.UP);
walk(EDirection.LEFT);
// js에서 사라짐.
const enum EDirection {
UP,
DOWN,
LEFT,
RIGHT
}
// ✅ 객체로 생성한다면 사라지지 않음.
const ODirection = {
UP: 0,
DOWN: 1,
LEFT: 2,
RIGHT: 3
} as const
// ❌
const ODirection = {
UP: 0,
DOWN: 1,
LEFT: 2,
RIGHT: 3
}
/*
{
UP: number,
DOWN: number,
LEFT: number,
RIGHT: number
}
로 추론 되어 하나하나 타입 지정을 해줘야함.
👉🏻 as const를 사용하여 해당 값들을 상수로 사용하겠다는 의미이다!!
*/
const ODirection = {
UP: 0,
DOWN: 1,
LEFT: 2,
RIGHT: 3
} as const;
// 데이터를 추출하여 타입으로 설정한다.
type Direction = typeof ODirection[ keyof typeof ODirection];
// type Direction = 0 | 1 | 2 | 3
/* const ODirection: {
readonly UP: 0;
readonly DOWN: 1;
readonly LEFT: 2;
readonly RIGHT: 3;
}
*/
function run(dir: Direction) {}
run(ODirection.UP);
👉🏻 typeof ODirection
ODirection객체를 추출하여 데이터로 사용 가능케한다.
👉🏻 keyof
는 객체의 key를 반환한다.
type AB = { a: "A" } | { b: "B" };
const a: AB = { a: "A" };
type AB = { a: "A" } & { b: "B" };
const ab: AB = { a: "A", b: "B" };
👾 객체 리터럴 대입 시 유의사항
type A = { name: string };
type B = { age: number };
type AB = A | B; // 넓은 타입
type C = A & B; // 좁은 타입
const ab: AB = { name: "Mark" };
const c: C = { name: "Mark", age: 25, married: false }; // error -> married 잉여속성 검사 실행
👉🏻 넓은 타입에 좁은 타입을 대입했는데 error발생
👉🏻 객체 리터럴을 바로 대입하면 잉여속성 검사가 실행됨!!
👾 중간에 데이터를 빼주면 error가 발생하지 않음.
const ab: AB = { name: "Mark" };
const obj = { name: "Mark", age: 25, married: false };
const c: C = obj;
🚨 error발생 원인은 user에 객체 리터럴을 대입하여 잉여 속성 체크가 발생한 것이다. 이때 할당가능 검사는 통과 하였지만 잉여 속성 체크는 통과하지 못했다. 그러므로 obj변수에 값 할당 후 user에 대입하면 할당 가능 검사만 체크하여 통과하게되어 error가 발생하지 않는다.(객체 리터럴을 직접 대입하지 않았기때문)
// 1
function a(): void {
return "hi"; // error
}
// 2
interface Human {
talk: () => void;
}
// 3
function a(callback: () => void): void {}
a(() => {
return "3";
});
declare function forEach(arr: number[], callback: (el: number) => void): void;
let target: number[] = [];
forEach([1, 2, 3], (el) => target.push(el)); // number를 반환
forEach([1, 2, 3], (el) => {
target.push(el);
}); // undefined를 반환
👉🏻 콜백함수 반환타입이 void여도 모두 error가 발생하지 않는다.
👾 unknown
try{ ...
} catch(error) { // 여기서 error는 자동으로 unknown타입을 가지게 됨
(error as Error).message;
}
👉🏻 어떤 타입의 error가 발생할지 모르기때문에 error 메세지 프러퍼티 사용할 때 타입을 지정한다.
Array.isArray(값)
을 사용한다.in연산자, 타입
을 생성해 구별한다!instanceof
를 사용한다.is
가 있으면 커스텀 타입 가드 함수이다!
👉🏻 is가 있어야만 타입 구분을 할수있다.
const x: {} = "hello";
const y: Object = "hi"; // null | undefined 제외!!
const yy: object = "hi"; // error
const z: unknown = "z"; // 모든 타입을 받을 수 있음
// v4.8: unknown = {} | null | undefined
if (z) {
z;
// v4.7에서는 z의 타입이 unknown으로 나오지만 v4.8에서는 {}으로 지정된다.
// if문에서 null | undefined이 걸러지니까 {}으로 지정됨.
}
👾 readonly
interface A {
readonly aa: string
}
const a: A = {aa: "Apple"};
a.aa = 'Angle'; // error
👾 인덱스드 시그니처
// type A = { a:number; b:number; c:number; }
type A = { [key: string]: number };
const obj: A = {
a: 123,
2: 2 // 2: string
}
👾 맵드 타입스
type Fruit = "apple" | "banana" | "orange";
type FruitInfoA = { [key in Fruit]: string };
type FruitInfoB = { [key in Fruit]: Fruit };
class A {
a: number;
b: string;
constructor(a: number, b: string = "123") {
this.a = a;
this.b = b;
}
x() {}
}
// typeof A == class의 이름인 A를 뜻함
// A는 new A()를 뜻함
const a: A = new A(123);
const b: typeof A = A;
class A {
#a: number = 123;
private b: string = "123";
x() {
console.log( this.#a, this.b );
}
}
const a: A = new A();
public | private | protected | |
---|---|---|---|
클래스 내부 | O | O | O |
인스턴스 | O | X | X |
상속 클래스 | O | X | O |
function add<T>(a: T, b: T): T {
return a + b;
}
// T에 타입 제한 걸기
function minus<T extends number>(a: T, b: T): T {
return a - b;
}
<T extends {...}>
<T extends any[]>
<T extends (...args: any) => any> // 모든 함수를 지정할 때 any사용해도됨. 함수라는 제한만 거는것이기 때문
<T extends abstract new (...args: any) => any> // class 자체를 넣을 경우
// <T,> : ,만 둬도 가능해짐
// const add = <T,>(a: T, b: T): T {
// return a + b;
// }
const add = <T = unknown>(a: T, b: T): T => {
return a + b;
}
add(1,2); // a,b는 number로 기본 타입에서 덮어씀
👉🏻 React에서 jsx문법과 혼동되어 추론이 잘 안될 수 있어 T에 기본타입을 지정한다.
👾 반환값
function a(x: string): number {
return +x;
}
type B = (x: string) => number | string;
let b: B = a; // ✅
function c(x: string): number | string {
return +x;
}
type D = (x: string) => number;
let d: D = c; // ❌
👾 매개변수
function a(x: number | string): number {
return +x;
}
type B = (x: string) => number;
let b: B = a; // ✅
function c(x: string): number {
return +x;
}
type D = (x: number | string) => number;
let d: D = c; // ❌
interface Add {
add(x: number, y: number): number;
add(x: string, y: string): string;
}
const add: Add = (x: any, y: any) => x + y;
add(1, 2); // ✅ number
add("1", "2"); // ✅ string
add(1, "2"); // ❌
class CustomError extends Error {
// 타입가드로 타입을 좁힘
response?: {
data: any;
}
}
(async () => {
try{
await axios.get();
} catch(error instanceof CustomError){
// instanceof를 쓰기위해 interface 대신 컴파일 시에도 코드가 남아있는 class를 사용하여 타입을 생성한다.
// 인터페이스를 타입가드로 사용할 수 없기때문
console.error(err.response?.data);
}
})();
타입스크립트 올인원 : Part1. 기본 문법편 강의를 요약 정리하였습니다.