본문 바로가기
Backend/JS & TS

타입스크립트 - part 1

by 퐁고 2023. 3. 23.
반응형

타입스크립트


  • Deno라는 런타임 환경에서 돌아감
    • js로 변환 후 Node.js 런타임에서 실행 → 이 과정을 컴파일이라함 (java와 다름, 단순 컴파일)

설치


sudo npm install -g typescript

// version 확인
tsc -v

// 실행하기 위해 npm package 설치 -> javascript(node.js) 프로젝트 만들기
npm init
// tsc 실행 할 때 컴파일 옵션을 정하기 위해 config 파일 만들기
tsc --init

ts.config.json 설정


{
  "compilerOptions": {
     "include": ["**/*.ts"],
     "exclude": ["node_modules"],
  }
}
  • include → 어떤 타입스크립트 파일을 자바스크립트 파일로 변환할거냐
    • "include": ["**/*.ts"], → 모든 폴더에 모든 파일을 변환할거임
  • exclude → 어떤 타입스크립트 파일을 변환 안할거냐
    • "exclude": ["node_modules"],
  • compilerOptions → 모든 타입스크립트 옵션들이 들어가있음

TSConfig Reference - Docs on every TSConfig option

실행


// ts파일 -> js파일로 변환
tsc 파일이름.ts
// js파일 생기고 그것을 node나 nodemon으로 실행

// 한 줄로 실행
tsc 파일이름.ts && nodemon 파일이름.js

// 모든 파일 변환
tsc

타입 주석


const a: number = 1;
const b: string = 'hi TS';

any - 다들어감 어떤 타입이든.. (쓰지않기 X)
number - interface, Long(bigint, smallint)
string - ``, '', ""
boolean - true, false (0,1 미포함)
object - {}, 객체의 any -> 모든 에러의 근원 (쓰지않기 X)
  • Number, String 이런거는 형 변환 함수이므로 타입을 명시할 때는 소문자로 적는다

타입 추론


let a = 1;

인터페이스


  • 명세, 타입, 클래스를 만들 때 사용
interface Person {
    name: string;
    age: number;
		city?: string; // ?는 값이 있을 수도 있고 없을 수도 있다.
}
const man = {
    name: 'kky',
    age: 26,
};

function prt(params: Person) {
    console.log(params.name);
//console.log(params.city ??'suwon'); === params?.city ? params.city : 'suwon';
}
prt(man);

익명 인터페이스 - 1번만 쓸 때

const man: {name:string; age:number; city?: string} = {
    name: 'kky',
    age: 26,
};

function prt(params:any) {
    console.log(params?.city ?? 'suwon');
}
prt(man);

배열


const arr1:number[] = [1, 2, 3];
const arr2:Array<number> = [1, 2, 3];

const arr3:string[] = ['a', 'b', 'c'];
const arr4:Array<string> = ['a', 'b', 'c'];

인터페이스 배열


interface Person {
    name: string;
    age: number;
    city?: string;
}

const arr5: Person[] = [
    {
        name: 'kky',
        age: 26,
        city: 'suwon',
    },
    {
        name: 'hhm',
        age: 26,
        city: 'juan',
    },
];
arr5.forEach((e) => console.log(e));
// arr5.forEach((e) => console.log(e?.city ?? 'default!'));

튜플


  • 배열의 길이와 원소를 바꿀 수 없다, 불변성 유지
  • 논리적 자료구조 실체가 없다.
const arr6: [number, string, object, any[]] = [1, 'hi', {}, []];
console.log(arr6);

// 값은 들어간다.
arr6.push('a');
console.log(arr6);

enum, literal


enum categoryEnum {
    H = 'H', // 무조건 할당해야함 초기화를 하지 않으면 0,1,2 순으로 자동으로 값을 가짐
    K = 'K',
    S = 'S',
}
const category: categoryEnum = categoryEnum.H;

function cate(category: any) {
    if (category === 'H') {
        console.log('5% 할인');
    } else if (category === 'K') {
        console.log('10% 할인');
    } else if (category === 'S') {
        console.log('80% 할인');
    } else {
        console.log('서버 멈춤');
    }
}
cate(category);

enum과 literal의 차이


enum sexEnum {
    Male = 'Male',
    Female = 'Female',
}

const sex: 'Male' | 'Female' = 'Male'; // 2개중 무조건 하나를 넣어야함 
const sex2: sexEnum = sexEnum.Male; // enum
  • literal은 1번만 사용할 때 쓰기 좋음 그 외는 enum
  • js에서 enum은 함수로 구현 (enum이 실제로 없기 때문)

함수 - function


function add(a: number, b: number): string {
    return String(a + b);
}

console.log(add(10, 20));

⭐️ return 문이 없거나 return; 인 경우 - void


function add(): void {
    console.log('리턴 문이 없습니다.');
}

add();

  • 함수의 파라미터는 () 안에서 타입 선언
  • 반환값 타입 선언은 () 옆에서 선언

화살표 함수의 타입 선언


const minus: (a: number, b: number) => string = (a, b) => String(a - b);
console.log(minus(20, 10));

기본 구조

const 함수명:(매개변수 타입) => 리턴 타입 = (매개변수 타입):리턴타입 => {
    return () => {}
}

const multiple:(a:number,b:number) => () => number = (a:number,b:number):() => number => {
    return () => {return a * b * 2};
}

type - 함수 or 타입이 길어질 때 사용


  • 기본 구조
  • type typeName(아무이름) = any(타입);
  • type을 사용하여 리팩토링 해보기

minus 함수

const minus: (a: number, b: number) => number = (a:number, b:number):number => a - b;
console.log(minus(20, 10));
type addFunc = (a: number, b: number) => number;

const minus: addFunc = (a: number, b: number): number => a - b;
console.log(minus(20, 10));

multiple 함수

const multiple:(a:number,b:number) => () => number = (
		a:number,
		b:number
):() => number => {
    return () => {
				return a * b * 2
};
}
type returnFunc = () => number;
type multiFunc = (a:number,b:number) => returnFunc;

const multiple: multiFunc = (
    a: number,
    b: number
): returnFunc => {
    return () => {
        return a * b * 2;
    };
};

에러문


  • 기본 에러 코드 예시
function sendErr(): void {
    console.log('에러 발생');
    return;
}
const result = sendErr();

throw는 return과 비슷 - 에러코드를 보내줌

function sendErr(): void {
    throw { errorCode: 500, message: 'err' };
    console.log('에러 발생');
    return;
}
const result = sendErr();
console.log(result);

클래스 - 접근 제한자 getter, setter


class UserInfo {
    public name: string; 
    protected age: number; 
    private _city: string; 

    constructor(name: string, age: number, city: string) {
        this.name = name;
        this.age = age;
        this._city = city;
    }
    getName(): string {
        return this.name;
    }
    getAge(): number {
        return this.age;
    }
    _getCity(): string {
        return this._city;
    }
    _setCity(newCity: string) {
        this._city = newCity;
    }
}
const user:UserInfo = new UserInfo('ky', 26, 'suwon');
console.log(user.getName());
console.log(user._getCity());
user._setCity('juan');
console.log(user._getCity());
  • 자바스크립트에서느 protected는 관례적 _ , private는 관례적 #을 붙이는데 타입스크립트는 private 앞에 _를 붙여준다.
  • 클래스는 new 클래스명으로 인스턴스를 만들 수 있지만, 타입으로도 쓸 수 있다.

클래스 - readonly


  • 읽기 전용
class LoginDataTransferObject{
    /*
		public readonly ID;
    public readonly PW;

    constructor(ID: string, PW:number){
        this.ID = ID;
        this.PW = PW;
    }*/

// 생성자 함수에서만 접근 제한자 사용가능 
		constructor(public readonly ID: string, public readonly PW: number){
        this.ID = ID;
        this.PW = PW;
    }

}
const loginDTO:LoginDataTransferObject = new LoginDataTransferObject('hi',1234);
loginDTO.ID = 'set'; // err!
console.log(loginDTO);

? → 값이 있을 수도 있고 없을 수도 있을 때

class LoginDataTransferObject {
    public ID;
    public PW?;

    constructor(ID: string, PW?: number) {
        this.ID = ID;
        if (PW) this.PW = PW;
    }
}
const loginDTO = new LoginDataTransferObject('hi');
// loginDTO.ID = 'set';
console.log(loginDTO);

추상 클래스


  • 추상 클래스는 특정 클래스의 상속 대상이 되는 클래스이며 좀 더 상위 레벨에서 속성, 메서드의 모양을 정의
abstract class Developer {
  abstract coding(): void; // 'abstract'가 붙으면 상속 받은 클래스에서 무조건 구현해야 함
  drink(): void {
    console.log('drink sth');
  }
}

class FrontEndDeveloper extends Developer {
  coding(): void {
    // Developer 클래스를 상속 받은 클래스에서 무조건 정의해야 하는 메서드
    console.log('develop web');
  }
  design(): void {
    console.log('design web');
  }
}
const dev = new Developer(); // error: cannot create an instance of an abstract class
const josh = new FrontEndDeveloper();
josh.coding(); // develop web
josh.drink(); // drink sth
josh.design(); // design web

대수 타입 - union, intersection


// 1. union - 합집합

let nameAge: string | number;
nameAge = 'kky';
nameAge = 26;

// 2. intersection - 교집합
interface IName{
    name:string
}
interface IAge{
    age:number
};
const age: IName & IAge = {
    name: 'kky',
    age:26, 
}

Key 값을 유동적으로 바꾸고 싶을 때


// interface IName {
//     name: string;
// }
// interface ISchool {
//     school: string;
// }
// interface ICity {
//     city: string;
// }

interface ISuperKey {
    [key: string]: string;
}

function prt(params: ISuperKey) {
    if ('name' in params) {
        console.log(params.name);
    } else if ('school' in params) {
        console.log(params.school);
    } else if ('city' in params) {
        console.log(params.city);
    }
}
prt({ name: 'kky' });

interface의 타입을 가진 키만 갖고 싶을 때


interface IBook {
    title: string;
    publisher: string;
    price: number;
    author: string;
}

function prt1(params: IBook, key: keyof IBook) {
    console.log(params[key]);
}

prt1(
    {
        title: 'ts',
        publisher: '인프런',
        price: 10000,
        author: 'kky',
    },
    'title'
);
  • keyof 를 적는다.

인터페이스 합치기


interface IUser {
    name: string;
    age: number;
}

interface IBook {
    title: string;
    price: number;
}
interface ICart {
    userName: string;
    userAge: number;
}

interface IUserBookCart {
    user: IUser;
    book: IBook;
    cart: ICart;
}
function searchBook(params: IUserBookCart['book']) {
    console.log(params);
}
searchBook({
    title: '객체지향의 사실과 오해',
    price: 20000,
});

'Backend > JS & TS' 카테고리의 다른 글

자바스크립트 - part 4  (0) 2023.03.23
자바스크립트 - part 3  (0) 2023.03.23
자바스크립트 - part 2  (0) 2023.03.23
자바스크립트 - part 1  (0) 2023.03.23

댓글