좌충우돌 개발자의 길

[TS] Typescript 기초 본문

STUDYING/Typescript

[TS] Typescript 기초

sustronaut 2022. 6. 12. 22:05

1. 컴파일

tsc 파일명.ts

타입스크립트 파일을 컴파일하고 index.html(예시)로 가져올 파일명.js를 생성

 

2. light-server

package.json 파일 옆에 항상 index.html 파일을 제공하는 간단한 서버

 

3. 타입스크립트 공부용 웹사이트

typescript playground

 

4. 타입 정의

콜론 + 원하는 타입명

function add(text:string, num:number){
	console.log(num1,num2);
}

function showItems(arr:number[]){
	arr.forEach((item)=>{
    	console.log(item);
    }
}

showItems([1,2,3]);

- 튜플 : 배열과 비슷한 모양으로 인덱스별로 타입이 다를 때 사용

let b:[string, number]

 

- void : 함수에서 아무것도 반환하지 않을 때 사용

- never : 항상 에러를 반환하거나 영원히 끝나지 않는 함수의 타입

- enum

비슷한 값들끼리 묶어둠, 차례대로 순번 배정해줌, 숫자, 문자열 가능

특정값만 입력할 수 있게 강제하고 싶을 때, 그리고 그 값들이 공통점이 있을 때 사용

enum Os{
	Window,  //1
    Ios,     //2
    Android  //3
}

enum Os{
	Windo=3,  
    Ios=10,     
    Android  // 자동으로 11배정
}

enum Os{
	Window = 'win',  
    Ios = 'ios',     
    Android = 'and'  
}

let myOs:Os; // myOs는 window, ios, android만 가능

myOs = Os.window //이렇게 사용

 

5. 인터페이스

property를 정해서 객체로 표현하고자 할 때 인터페이스 사용

type Score = 'A' | 'B' | 'C' | 'F';

Interface User {
	name: string;
    age: number;
    gender? : string; //옵션 : 써도 괜찮 안써도 괜찮
    readonly birthYear : number; // 읽기전용으로 수정 불가
    [grade:number] : string; // 문자열 인덱스
    [grade:number] : Score; // Score의 값만 들어가게 설정 다른거 들어가면 에러뜨게 함
}

let user: User = {
	name: 'xx',
    age: 30,
    birthYear: 2000,
    1 : 'A',
    2 : 'B',
}

user.age = 10;
user.gender = "male";
user.birthYear = 1900; //수정불가로 에러

- 인터페이스로 함수 정의하기

interface Add {
	(num1:number, num2:number): number; // 인자값과 반환값 설정
}

// 함수 1
const add : Add = function(x, y){
	return x+y;
}

// 함수 2 : 화살표 모양
const add : Add = (x, y) => {
	return x+y;
}

add(10,20);

- 인터페이스로 클래스 정의하기

--> implements를 써줘야함

- 인터페이스는 확장도 가능하다 : extends

extends는 여러개 확장도 가능함

// 위의 코드 연장선

interface Benz extends Car { //Car의 속성들이 추가되어 Benz 확장됨
	door: number;
    stop(): void

}

const benz : Benz = {
	door: 4,
    stop(){
    	console.log("wow");
    },
    color : 'green',
    wheels: 3
    start(){
    	console.log("start");
    }
}

// 여러개 extends 추가 가능
interface Car {
.. //생략
}

interface Toy {
..//생략
}

interface ToyCar extends Car, Toy{
	...//생략
}

 

6. 함수

function add(num1: number, num2: number): void { //반환값 타입 void로 설정
	console.log(num1+num2);
}

function hello(name?: string) { //name은 있어도 괜찮 없어도 괜찮
	return `hello, ${name || "world"); //name없으면 world로 출력
}

function hello2(name= "world") { //default 값으로 설정해도 string으로 인식해줌
	return `hello, ${name); 
}

const result = hello();
const result2 = hello2();


//선택매개변수가 필수매개변수보다 앞에 오면 에러
function hello(name?: string, age: number) {
	...
}

//선택매개변수를 앞에 쓰고 싶을때
function hello(name: string | undefined, age:number){..}

// ...는 전달받은 매개변수를 배열로 바꿔줌
function add(...nums: number[]){...}

add(1,2,3,4,5);


// this의 타입 정하기
interface User {
	name: string;
}

const Sam: User = {name:'Sam'}

function showName(this:User, age:number, gender: 'f'|'m'){
	console.log(this.name, age, gender);
}

const a = showame.bind(Sam); // bind를 이용해서 this를 Sam객체로 강제

a(30,'f');

- 함수 오버로드

age의 타입에 따라서 리턴해주는 결과값이 달라짐(객체이거나 string) --> 이럴땐 overrode 사용
함수 오버로드 : 전달받은 매개변수의 개수나 타입에 따라 다른 동작을 하게 하는 것

오버로드 전
오버로드 후

 

7. 리터럴, 유니온/교차 타입

- 문자열 literal : 정해진 string을 가진 것

ex/ const userName1 = "bob";  //bob만 가능

- 숫자형 literal : 정해진 숫자만 가능

문자형 literal
숫자형 literal

+ let userName2 = "Tom"; //string 으로 입력 가능하다고 뜸

userName2=3: // 에러

let useName2: string | number ="Tom"; // 이렇게 지정해주면 위의 에러가 안뜸

 

- 유니온 타입 : |  (or)

식별가능한 유니온 타입 : 동일한 속성의 타입을 다르게 해서 구분할 수 있는 것

if로 구분하고 gift.start() 하면 에러

- 교차 타입 : & (and)

여러 타입을 합쳐서 사용 -> 여러개의 타입을 하나로 합칠 때 사용

모든 속성을 다 적어줘야함 (ex/ Car, Toy)

 

8. 클래스 Class

1. 타입스크립트에서 class를 작성할 때 멤버변수(메소드 밖에서 선언된 변수)는 미리 선언해줘야함 (ex/this.color의 color)

2. 1처럼 미리 멤버변수 선언하지 않고 접근 자연자, readonly 사용하기

public
readonly

- 접근 자연자 : public , private, protected

public : 자식 클래스나 클래스 인스턴스에서 접근 가능 (기본값)

private : 자식 클래스에서 사용x, 해당 클래스에서만 사용 가능 (private name 말고 #name이렇게 표현도 가능)

protected : 자식 클래스에서 통제 가능하나 클래스 인스턴스에서는 불가능

private시 Car클래스에서만 name 사용 가능
protected

 

- readonly : 수정 불가능

바로 위의 코드에 readonly name: string = "car"로 바꾸고 z4.name = "zzzz4"; 입력시 에러뜸 

 

- static : 정적 멤버변수를 만들 수 있음

접근시 this가 아닌 class 명을 씀 -> this.wheels (x) Car.wheels (o)

 

- 추상 class : abstract 를 사용해서 만듦

추상 : property나 메서드 이름만 만들어주고 구체적인 기능은 상속받는 쪽에서 해주는 것

추상클래스는 const car = new Car("red"); 처럼 new를 사용해서 객체만들기 불가능 -> 상속을 통해서만 가능 (extends)

추상 클래스 내부에 추상 메서드는 반드시 상속받은 쪽에서 구체적인 구현 해야함

 

9. 제네릭 Generics

- 제네릭 : 클래스나 함수, 인터페이스를 다양한 타입으로 재사용 가능

- 사용 이유 : 아래와 같이 필요한 타입들을 줄줄 적지 말고 간단하게 표현할 때 사용

 

- 제네릭 사용 방법

     - <T> : 타입 파라미터로 어떤 타입을 전달받아서 이 함수에서 사용할 수 있도록 함

     + <number | string> : 특정 파라미터를 강조하고 싶을 때 이렇게 표현 가능

첫번째 제네릭 예시
두번째 제네릭 예시
이렇게도 설정 가능!

 

- extends를 써보자

     - Book은 name이 없으니 (모든 매개변수에 name이 있다고 단정할 수 없어) 에러가 발생

- 에러 발생한 코드

   - T타입의 데이터가 올 건데 그 타입은 name이 string인 객체를 확장한 형태이다

       -> name이 없거나 string 아닌 것이 오면 에러 발생하게 설정

extends를 사용한 코드

 

10. 유틸리티 타입 Utility Type

1) keyof

-> keyof를 사용하면 유저인터페이스 key값들을 유니언 형태로 받을 수 있음 

 

2) partial<T>

-> 모든 property를 옵션으로 바꿔줌

-> 관리자 (admin) 유저는 id값, name값만 있으면 되니까 Partial를 사용해서 옵션형태로 설정

 

3) Required<T>

-> 모든 property를 필수로 바꿔줌

-> age가 옵션으로 설정되어있지만 Required를 쓰면 age가 필수가 되어 age 안 쓰면 에러 뜸

 

4) Readonly<T>

-> 읽기 전용으로 바꿔줌 -> 할당은 가능하지만 수정은 불가능해짐

 

5) Record<K,T>

-> K : key , T: type

 

- 예제1

전 -> 후 

- 예제2

예제2

-> User의 key값들을 사용하고, type은 boolean이다

 

6) Pick<T,K>

-> T타입에서 K property만 골라서 사용

-> User에서 id랑 name만 가져와서 사용

 

7) Omit<T,K>

-> 특정 property를 생략하고 쓸 수 있음

-> User에서 age와 gender property만 생략해서 사용

 

8) Exclude<T1, T2>

-> T1에서 T2를 제외하고 사용 

-> omit과 다른점 : omit은 property로 제거, exclude는 type으로 제거

-> T1에서 number와 string type을 제외한 애들만 사용 (==boolean만 사용 가능)

 

9) NonNullable<Type>

-> null, undefined 을 제외한 타입 생성

-> T1에서 null과 undefined를 제외한 애들만 사용 (==string, void만 사용 가능)