관리 메뉴

흰둥씨의 개발장

[typescript] 타스 왜 씀?/ 설치 / 기본 타입 / 인터페이스(interface) 본문

[오늘의 공부]/typescript

[typescript] 타스 왜 씀?/ 설치 / 기본 타입 / 인터페이스(interface)

돈워리비해삐 2023. 6. 14. 03:33

 

타입시스템

  - 정적 타입시스템 : C, JAVA, 코드 실행이전 변수의 타입을 고정적으로 결정함

  - 동적타입 시스템 : python, Javascript, 코드 실행하고 나서 그때마다 유동적으로 변수의 타입을 결정함 

 

https://www.typescriptlang.org/

Javascript는 동적언어로 런타임에 타입이 결정됨 / 런타임에 오류를 발견함 => 사용자가 오류같은 걸 고스란히 볼수 있음
                        변수의 타입이 하나로만 고정되지 않음  => 오류를 좀 내줘야 하는데 그냥 실행되어 버림(예기치 못한 오류)


Java는 정적언어로 컴파일 타임에 타입 결정함 / 컴파일 타임에 오류를 발견함 => 실행전 에러인지하기 좋음
              코드 실행 전 모든 변수의 타입을 결정함 (유연하지 못함)

Typescript는  동적타입 시스템(모두 타입지정안해도 됨) + 정적타입시스템의 안정성(실행전검사)을 모두 사용함
(변수에 타입을 모두 지정할 필요는 없음, 타입지정 안된 변수는 추론해서 에러 내줌  =  점진적 타입시스템 = 유연)

function add(num1, num2){
    console.log(num1+num2);
}

add(); //NaN
add(1); //NaN
add(1,2); //3
add(3,4,5); //7
add('sival ','roma'); //sival roma

ㄴ위 코드는 자바스크립트에서는 에러가 나지 않음 
ㄴ타입스크립트에서는 에러가 남 => 파라미터의 타입을 지정하고 에러뜬 부분을 미리 수정할수 있음


일반적인 컴파일 과정  

Javascript  ===> AST (추상 문법 트리) ===> 바이트 코드 ===> 실행


타입스크립트의 컴파일 과정

Typescript ===> AST (추상 문법 트리) ===> 타입검사( 검사실패시 컴파일 종료 ) ===> (검사성공시) Javascript 로 변환 
                                                                                                                                                                       ||
                                                                                                                                   타입검사를 통과함(안전), 타입관련 문법은 사라짐

Typescript 설치방법

1. Node.js설치
2. 프로젝트 폴더 터미널에서 아래 명령어 실행 

 //HTML CSS JS 개발시 Typescript 쓸 때
npm install -g typescript

//React에서 typescript사용할 경우
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
//React프로젝트 새로 생성시에는 아래 코드
npx create-react-app 생성할폴더명 --template typescript

//Vue에서 typescript쓰려면
//작업 폴더에서 터미널 오픈후 아래 명령어 입력
vue add typescript
//vue파일에서 타입스크립트 쓰려면... 
<script lang="ts">
  
</script>

//설치 방법 2
npm init //node 초기화하고나서 
npm i @types/node
sudo npm install typescript -g

타입스크립트 컴파일러 설치 (설치확인은 tsc -v 해보기)

 

설치후 src/index.ts 생성하여 작업후 터미널에서 아래 명령어 실행하면 작성한 index.ts가 컴파일하여 index.js파일 생성함

tsc src/index.ts
tsc -w  //모든 파일 자동 변환 w는 watch의미
        //(실시간 감지해서 변환해 줌, root dir에서 사용할 것, 터미널에서 중지하면 실시간 감지 종료됨)

ts로 작업하고 계속 js파일로 갱신하여 작업하기 힘들기 때문에 ts-node를 설치하여 이용하면 편리함 

 sudo npm install ts-node -g    //설치명령어
 ts-node src/index.ts           //실행명령어 tx+node라서 바로 실행해 줌

타입스크립트 컴파일러 옵션 (얼마나 엄격하게 타입 검사할지 , 자바스크립트 코드 버전은 어떻게 할지 ... )

tsc --init   //tsconfig.json파일 생성 (컴파일 옵션설정 파일)

ㄴtsconfig.json수정했는데 적용 안 되면 cmd+shift+p 해서 restart하기

{
  "compilerOptions": {
    "target": "ESNext", //자바스크립트 최신 버전으로 설정
    
    "module": "ESNext", //CommonJS(CJS) vs ESNext 어떤 모듈 문법 쓸건지***
    
    "outDir": "dist", //컴파일된 js파일이 어디에 생성되면 좋겠는지 설정
    
    "strict": true, //엄격하게 타입을 검사함 (true : 점진적 타입시스템을 못 씀)
    
    "moduleDetection": "force", // ts는 모든 파일이 전역(global)모듈로 취급되기 때문에 파일마다 독립적인 모듈,개별모듈로서 작동하도록 설정 
    // 아니면 ts작성시 export와 같은 키워드를 일부러 넣어서 사용하면 그 파일은 개별적 모듈됨
 
    "noImplicitAny": true, //any타입이 의도치 않게 발생하는 경우 에러를 띄워주는 설정

    //"strictNullChecks": "false" 
    //Null타입이 아닌 변수에 임시로 null값 넣을 일이 많으면 쓰기(strict옵션 true면 널체크옵션의 기본은 true로 설정됨)
  },
  
  "ts-node": {
    "esm": true, //ts node는 commonJS를 기본으로 쓰기 때문에, 이 옵션을 추가해서 ESM모듈시스템으로 동작하도록 설정
    //(package.json에도 "type":"module"추가하기)
    //만약에 해당 옵션 추가안하면 moduleDetection에 의해 js에 생성된 export{}키워드를 node가 이해하지 못함 
  },
  
  "include": ["src"] //src내 파일을 모두 컴파일 해라는 명령 => 이 tsc만 터미널에 입력하면 모두 컴파일됨
}


//***commonjs는 require 문법(IE호환원하면 이걸로 가야함)
//***es2015, esnext는 import 문법

https://www.typescriptlang.org/tsconfig 


Primitive Type(원시타입)

: 하나의 값만 저장하는 타입(number, string, boolean, null, undefined)

//number
let num1 : number = 123;
let num2 : number = -123;
let num3 : number = 0.1;
let num4 : number = -0.1;
let num5 : number = Infinity;
let num6 : number = -Infinity;
let num7 : number = NaN;

num1.toFixed();

//string 
let str1 : string = "hi";
let str2 : string = 'hi';
let str3 : string = `hi`;
let str4 : string = `hi ${num1}`;

str1.toLocaleLowerCase();

//boolean
let boo1: boolean =true;
let boo2: boolean =false;

//null
let 널 : null = null;

//undefined
let undef : undefined = undefined;

//리터럴 타입
let numA : 10 = 10; // numA에는 숫자 10 외에는 다른 숫자도 들어갈 수 없음
let strA : "hi" = "hi";  
let booA : true = true;

 

null, undefined, any, unknown

let a: null = null;
let b: undefined = undefined;

//any  => 타입스크립트를 쓰는 의미가 없어짐
let c: any = 'hi';
c = 123;
c = undefined; 

//unknown  => any보다는 안전함 
let d: unknown = 'kim';
d = 123
d = undefined;

let name : string = d;  // 불가 string타입에 unknown타입의 값 할당 불가
name = c; // 가능 string타입에 any타입의 값 할당 가능 

d * 2; //불가 수학연산은 number타입만 가능하고 unknown불가
c * 2; //가능 any타입은 수학연산에서도 에러 안남

 


기본적 타입스크립트 구성

let age : number = 30;
let isAdult : boolean;
let a1 : number[] = [1,2,3];
let a2 : Array<number> = [1,2,3];

let week1 : string[] = ['mon', 'tue', 'wed'];
let week2 : Array<string> = ['mon', 'tue', 'wed'];

//week1.push(1);  //불가능 => 문자열로 구성된 배열 week1에 숫자 푸시안됨

배열타입 

//배열 
let numArr : number[] = [1,2,3];
let strArr : string[] = ['im', 'groot'];
let booArr : Array<Boolean> = [true, false]; //제네릭 사용

다차원 배열 

//다차원 배열(배열안의 배열 가진 것) 타입 정의 하기
let doubleArr : number[][] =  [  //number[]숫자타입의 배열을 []배열안에 저장
    [1,2,3],
    [4,5],
    ]

객체(Object)

let acc : { shoe?: string } = { shoe : "신발" }; //? 는 optional
type MyType = {
  [key :string] : number,  //키를 문자로 한 모든 값은 number => index signature
}
let 철수 : MyType = { 
  age : 50,
  weight : 100,
}

 

함수 

function add (x:number) : number{ //매개변수x의 타입은 number, 반환값은 number
	return x + 1;
    }
   
   
function 곱하기(x: number | string){ //매개변수 타입이 string이거나 number이기 때문에
	if (typeof x === 'number'){ //조건항 없이 
    	return x * 1;              //number만 가능한 연산자 쓸 수 없음
      }
   }

 


튜플(Tuple) : 길이와 타입이 고정된 배열 

let b: [string, number]; //변수b의 타입은 첫번째 값은 문자열, 두번째 값은 숫자인 배열
b = ['a', 1] //가능
//b = [1,2] //불가능

b[0].toLowerCase(); //가능
//b[1].toLowerCase(); //불가능

let tup : [number, number, boolean] = [1,2, true]; //변수 tup은 첫번째 값 숫자, 두번째값 숫자
//tup = [1,2,true,4] ; //불가능 -> 네번째 값은 타입 설정되지 않아서, 값 할당 불가 
//tup = ['1','2'] //불가능 -> string 불허
//tup = [true, 1,2,3] //순서 바꿔도 안됨

tup.push(1); // 튜플로 타입정의한 배열에 배열 메서드 사용하면 길이를 넘기더라도 에러를 밷어내지 않음 (유의할 것)
tup.pop(); //에러 없음 
tup.pop(); //에러 없음 
tup.pop(); //에러 없음
//튜플을 이용해서 다차원 배열 오류 해결하기
/* 
let user = [
        ["a",1],
    	["b",2],
    	["c",3],
    	["d",4],
    ];
*/
    //위와 같은 user에 [5,"e"]가 추가 된다고 할 때
    아래와 같이 코드를 바꿔주면 쉽게 에러 확인가능 

let user : [string, number][] = [ //[문자열,숫자열]을 저장하는 배열
        ["a",1],
    	["b",2],
    	["c",3],
    	["d",4],
    ];

 

void: 함수에서 아무것도 반환하지 않을 때 주로 사용
never : 항상 에러를 반환하거나, 영원히 끝나지 않는 함수

function sayHi():void{
	console.log('Hi');
    };

function showError():never{  //에러반환
	throw new Error();
    };
    
function infloop():never{  //영원히 안끝남
	while(true){
    //...
    }
   }

 

enum

enum OS{
	window = 3, 
	IOS,        //IOS=4로 
	Android     //Android=5로 자동 할당됨
  }
  
console.log(OS[3])  //window
console.log(OS[4])  //IOS
console.log(OS['Android'])  //5

let myOs:OS; //myOs에 3가지만 입력가능함

 

 


 

interface :  property를 정의해서 객체로 표현하고자 할 때 사용함

type Score = 'A' | 'B' | 'C' | 'F' ; //Score에 지정한 값 외에는 입력할 수 없음
interface User {
    name : string;
    age : number;
    gender? : string;  //? 붙이면 있어도 되고 없어도 되는 optional한 속성이 됨
    readonly birthYear : number;  //readonly를 사용하면 생성시에만 할당가능
    [grade:number] : Score; //number를 key로 Score에 지정한 값을 value로 받을 것임  
}

let user : User = {
        name: 'string',
        age: 30,
        birthYear : 2000, //생성시
        1:'A', //[grade:number] : Score;
        2:'B', //[grade:number] : Score;
        
          
}
 console.log(user.age) // interface없이 user.age는 없는 값
 
 // user.birthYear = 1900;  //불가  readonly로 설정되어있기 때문에

 

interface로 함수 정의도 가능 

interface Add {
	(num1:number, num2:number) : number; //(파라미터의 타입) : 리턴값 타입
}

const add : Add = (x, y) => {  // add라는 함수에 Add interface로 타입정의 
	return x + y;
}

// add('a',10)//에러뜸
add(1,2) //3


interface isAdult {
	(age:number) : boolean;
}
const age :IsAdult = (age) =>{
	return age>19;
}
age(33); //true
age(18); //false

 

interface로 class정의 가능하고, implements키워드 사용
interface를 확장할 때는 extends키워드 사용

interface Car {
	color:string;
	wheels:number;
	start() :void;
}

class BMW implements Car {
	color;
	wheels=4;

	constructor(c:string){ //생성될 때 색상을 입력받음
		this.color = c;
	}
	start() {
		console.log('go...');
	}
}

const b = new BMW('green'); //변수 b에 클래스 생성하여 할당
console.log(b); // 클래스 BMW출력됨
b.start(); //go...


//extends
interface Benz extends Car { //Car의 속성을 모두 받아서, 확장된 interface Benz만듦
    door:number;
    stop():void;
}

const benz : Benz = {
	color:'red',
	wheels:4,
	start(){
    	console.log('go...');
	},
	door : 5,
    stop(){
    console.log('stop');
    }
}

interface CAR extends Car, Benz { //인터페이스 여러개 모아서 확장가능 
	price:number;
}

 

'[오늘의 공부] > typescript' 카테고리의 다른 글

[typescript] 유틸리티 타입(Utility type)  (0) 2023.06.16
[typescript] Generic  (0) 2023.06.16
[typescript] 클래스  (0) 2023.06.15
[typescript] 리터럴과 유니온/교차 타입  (0) 2023.06.15
[typescript] 함수  (2) 2023.06.15