TypeScript 기초

Churro.·2022년 4월 6일
0

TypeScript란?

설치 및 실행

VSCode -> Open files -> 하단에 새로 만들기 -> 폴더명 입력 -> 더블클릭 -> 안에 text.ts파일 하나 만들기

npm init
npm install

타입스트립트를 global로 설치 (어디서나 실행가능하게끔)

npm i typescript -g

tsc는 TypeScript compiler의 약자. TypeScript compiler를 사용하겠다는 명령어.
test.ts는 파일명.
tsc는 TypeScript코드로 쓰여진 test.ts파일을 JavaScript파일로 변경해준다.

tsc test.ts

설정파일 생성 (tsconfig.json)

tsc --init
tsc

파일 수정됐을마다 새로 컴파일 시키기 (watch mode)

tsc -w

선언과 할당

선언

let a;

할당

let a : string;
a = "Jenny";

혹은

let a = "Jenny"

이렇게 하면 a의 type은 바로 string으로 지정된다.


TS Type vs. JS Type

  • TS는 static type : 개발하는 중간에 type을 check
  • JS는 dynamic type : 개발할 때는 알 수 없고, runtime에 돌입해야만 잘못된 것인지 알 수 있다.
//JS
function add(n1, n2) {
	if(typeof n1 !== 'number' || typeof n2 !== 'number) {
    	throw new Error('숫자만 입력해라잉')
    }
    return n1+n2
}
const result = add(39, 28)

//TS
function add(n1, n2) {
	return n1+n2
}
const result = add(39, 28)

Interface

function hello1 (person : {name:string; age:number}) : void {
  console.log('안녕! 나는 ${person.name}이야');
}
// 출력만 할꺼니까 return type은 void

const p1: {name:string; age:number} = {
  name : "Jenny",
  age: 26,
}

// p1은 Jenny, 26 값을 가진 객체
// 같은 구조를 가지고 있기 때문에 다음과 같이 hello1에 넣을 수 있다

hello1(p1);

근데 지금 {name:string; age:number} 가 중복이 되니, Person1이라는 데이터구조 (=interface)로 만들어 사용해보자.

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

function hello1 (person : Person1) : void {
  console.log('안녕! 나는 ${person.name}이야');
}

const p1: Person1 = {
  name : "Jenny",
  age: 26,
}

Indexable Types

interface Person3 {
  name:string;
  age?:number;
  [index:string]:any;
}

const p32: Person3 = {
  name = 'Anna',
  sisters = ['Sung', 'Chan'] 
}

🍟 index가 sisters이고, 
   any니까 ['Sung', 'Chan']과 같은 배열도 가능, 객체도 가능, 모든 type 가능!!

Indexable type 형태는
[ ] : 어떤타입가능한지

객체 a 가 있다고 하면
a[index] 이렇게 들어오는건데 index자리엔 string만 허용.
그럼 예를 들어 a['Jenny'] 이렇게 들어온다는 것.
(JS에서 property 생성해서 넣어주는 원리와 동일)

즉,
a['Jenny'] 의미와 같은 게 [index:string] 이라고 볼 수 있다.
근데 a['whatever']처럼 property의 실제 값은 아무거나 가능하므로 뒤에 :any 를 붙여주는 것.

interface를 class로 사용하기

사용한다기보다는 interface에 있는 내용을 바탕으로 Person이라는 class를 만들어 내는 것이다.

implements 사용

interface IPerson1 {
  name: string;
  age?: number;
  hello(): void;
}

class Person implements IPerson1 {
}

이런 식으로 있으면,
Person 의 빨간밑줄 클릭하면 다음과 같이 자동완성된다.

class Person implements IPerson1 {
 name: string;
  age?: number | undefined;
  hello(): void {
    throw new Error("Method not implemented.");
  }
}

그럼 이제 name에 빨간밑줄이 뜬다.

Property 'name' has no initializer and is not definitely assigned in the constructor.

Why?
name의 초기값이 지정되어있지 않다는 의미.

name의 초기값 지정해주기

constructor 사용

class Person implements IPerson1 {
 name: string;
  age?: number | undefined;
  
  constructor(name : string) {
    this.name = name;
  }
  hello(): void {
    throw new Error("Method not implemented.");
  }
}

const person = new Person("Jenny") 

person에 마우스를 갖다 대면, Person이라는 class type으로 지정이 되어있는 걸 볼 수 있다.
근데 IPerson1이라는 interface로부터 구현(implements)됐기 때문에,
const person : IPerson1 = new Person("Jenny")
이렇게 쓸 수도 있다.

const person = new Person("Jenny") 
person. 다음에 name, age?, hello를 쓸 수 있도록  (interface에 있는 내용임)

즉, 이 interface로부터 구현된 아이는

name: string;
age?: number;
hello(): void;

를 만족해야 한다.
이걸 만족하는 class를 만들어서 사용가능.
그 class는 class 이름으로 type을 부를 수 있지만, interface이름(IPerson1) 으로 부르는 게 더 정확한 표현이다.

person.hello();

이렇게 함수를 실행할 수 있다.

이제는, 외부로는 interface만 노출하고, 내부적으로는 class 내부 구현하는 방식으로 작업하게 된다.

interface extends interface

interface 끼리 상속하기

interface IPerson2 {
  name: string;
  age?: number;
}
  
interface IKorean extends IPerson2 {
  city: string;
}
// 작은부분 extends 큰부분
// IKorean이 IPerson2의 형태를 상속한다.
// 그래서 IKorean 형태는 이렇게 된다:
  name: string;
  age?: number;
  city: string;
  
  
const k : IKorean = {
  name : "Jenny",
  city: "Seoul",
}  
// k는 객체
// "IKorean의 type형태를 가진다"라는 뜻이다.

function interface

함수를 interface로 만들어내기 (타이핑하기)

interface HelloPerson {
  (name: string, age?: number) : void;
}
// return type은 void

const helloPerson : HelloPerson = function(name:string){
// helloPerson이라는 함수는 HelloPerson이라는 타이핑을 할거다.
  console.log(`안녕. 나는 ${name}이야.`)
//helloPerson은 HelloPerson형태와 같아야 한다.
🍟 helloPerson은 뒤에 function보다는, HelloPerson와 더 연관성이 크다! 형태 동일해야.

//실행
helloPerson('Jenny')
helloPerson('Jenny', 26)  
  //function에 age부분 안써도 이렇게 실행가능. 
  //이 말은 즉슨, helloPerson함수에겐 HelloPerson interface의 형태가 가장 중요+영향력.
}
profile
I, sum of records.

0개의 댓글