타입스크립트 배워보기!
목차
타입스크립트 개요
일반 자바스크립트
컴파일되는 자바스크립트 상위 호환(Superset)
이다.
즉 자바스크립트
의 모든 구문과 기능을 지원 하며 자바스크립트
에 포함 되지 않은 더 풍부한 구문과
추가 기능을 제공한다.
JS에서 변수는 문자열, 숫자, 불린 등 여러 타입의 값을 가질 수 있으므로 약한 타입 언어
라고 표현하여 비교적 유연하게 개발할 수 있는 환경을 제공하지만 런타입 환경에서 쉽게 에러가 발생하는 단점
이 있다.
반대로 타입스크립트는 강한 타입 시스템
을 적용하여 에러를 컴파일 환경에서 코드를 입력하는 동안
체크할 수 있다.
그리고 타입스크립트는 프로그래밍 언어인 동시에 컴파일러이다. 타입스크립트를 자바스크립트로 컴파일한다.
버그를 최소화 -> 쉬운 유지 보수 -> 질 좋은 코드
타입스크립트 설치
공식홈페이지로 이동하여 install locally
버튼을 클릭하면 npm
으로 설치할 수 잇는 명령어가 나온다
npm install typescript
타입스크립트 다루기
간단한 예제들을 통해 배워보겠다.
아래와 같이 매개변수에 타입을 지정하여 함수를 실행할 것이다. 타입스크립트는 컴파일러이기 때문에
tsc 파일명
을 통해 자바스크립트로 변환 하자.
그럼 같은 이름에 js파일
이 생성되면 node
명령어를 통해 실행할 수 있다.
tsc -w 파일명
을 사용하면 따로 컴파일 명령어를 사용하지 않아도 실시간으로 컴파일을 해준다
app.ts
// 매개변수에 타입을 지정
function addName(name: string) {
console.log(name)
}
// 해당 인자로 1 숫자를 넣으면 에러가 발생한다
addName("철수")
// app.ts 컴파일
tsc app.ts
// 위 컴파일이 끝나면 app.js 생성
// "김"출력
node app.js
------------------------------
철수
중복된 함수 구현에러 발생시 (vscode 버그라고함)
tsc --init
으로 해결 가능
1. Static Typing
타입스크립트의 큰 특징 중 하나는 Static Typing
기능을 자바스크립트 언어에 지원하는 것이다
Static Typing?
타입을 선언하고 선언된 타입의 맞는 값만 할당이나 반환 되는 것
Type Inference (타입 추론)
타입스크립트에서는 타입 표기가 없는 경우 코드를 읽고 분석하여 타입을 유추 할 수 있는 특징이 있다
app.ts
// 아래와 같은 코드를 입력시 두번째 a에서 할당값이 숫자가 아니기 때문에 에러가 발생함
let a = 5;
a = 'k'
// 타입스크립트는 자바스크립트의 superset이기 때문에 정상적으로 컴파일 된다.
let a = 5;
a = 4
// 이미 객체 property의 값의 타입 추론이 됨
// 할당 값을 바탕으로 타입 추론
let person = {
name: "철수",
age: 31
address: "서울"
action: function() {
console.log(`${this.name}는 ${this.address}에 산다`)
}
}
// 위 주석 때문에 name에 숫자로 재할당 하려하면
// 에러 발생
person.name = 123
// function에 마우스를 오버하면 -연산자를 통해 함수의 리턴 타입이 숫자일 것을 추론
function add (number) {
return 1 - number;
}
Type 명시
변수를 선언할 때, 변수 값의 타입을 명시함으로써 변수 값의 데이터 타입을 지정
let n: number = 1
let name: string = "철수"
let age: number = 23
let gender: string = "남"
let address: string = "서울"
let adult: boolean = true
// 다음과 같이 `object`로 함수에서 반환되는 값의 타입을 지정해 줄 수 있다.
// 아래와 같이 반환되는 타입을 any, void가 아닌 값을 지정시 return값이 반드시 와야함
function getPerson(age: number):object {
return null
}
// 아래처럼 명시된 구조로 이용할 수 있다.
// 반환되는 객체의 구조를 타입으로 지정
// 아래와 같이 반환 타입을 명시할 수 있지만 지저분해 보이는 것을
// interface를 이용하여 효과적으로 처리할 수 있다.
function getPerson(age: number):{
n: number
name: string
age: number
gender: string
address: string
adult: boolean
} {
return null
}
Interface로 타입의 구조를 정의하는 방법
타입스크립트에서는 interface
네이밍시 i
를 붙이지 않고 대문자로 이용
interface PersonCard {
n: number
name: string
age: number
gender: string
address: string
adult: boolean
}
// person인터페이스를 이용하여 반환값이 person구조를 가지도록 강제됨
function getPerson (n: number): PersonCard {
return {
n: 1,
name: "철수",
age: 31,
gender: "남",
address: "서울",
adult: true
}
}
// 아래와 같이 반환값이 다르다면 에러가 발생
function getPerson(n: number): PersonCard {
return "Hello world"
}
위 와 같이 인터페이스를 타입으로 가지는 값은 인터페이스의 구조를 그 값으로 가지도록 강제된다
?
선택적 프로퍼티 활용
강제되는interface
를 좀 더 유연하게 이용하기 위해서는 interface
내 에 정의된
특정 프로퍼티(선택적 프로퍼티)가 있어도 되고 없어도 된다면 Option의 기호인 ?
를 붙여서 사용한다
let person = {
n: 1,
name: "철수",
age: 31,
gender: "남",
address: "서울",
adult: true
}
// 특정 프로퍼티 뒤에 ?를 붙이면 유연하게 사용 가능
interface PersonCard {
n: number
name: string
age?: number
gender: string
address: string
adult: boolean
}
// age가 있어도되고 없어도 된다
function getPerson (n: number): PersonCard {
return {
n: 1,
name: "철수",
gender: "남",
address: "서울",
adult: true
}
}
// 아래와 같이 interface의 코드를 재사용이 가능하다
function savePerson(person: PersonCard): void {
}
savePerson(person)
인터페이스에 프로퍼티로 메소드도 정의할 수 있다
메소드는 객체내에서 정의된 함수이므로 아래처럼 표현 가능
interface PersonCard {
n: number
name: string
age: number
gender: string
address: string
adult: boolean
// 아래와 같이 메소드를 정의 가능
// addComment(comment: string): string
addComment?:(comment: string) => string
}
readonly
로 읽기 전용 정의
readonly
속성을 추가하여 읽기 전용 프로퍼티로 정의 가능하다
let person = {
n: 1,
name: "철수",
age: 31,
gender: "남",
address: "서울",
adult: true
}
interface PersonCard {
readonly n: number
name: string
age: number
gender: string
address: string
adult: boolean
addComment?:(comment: string) => string
}
function savePerson(person:Person): void {
Person.n = 2; // readonly 속성 때문에 변경되지 않고 에러가 발생한다
}
savePerson(person)
❗
interface
는 코드가 렌더링 될때 아무런 영향력이 없다 타입스크립트 컴파일러가 자바스크립트로 컴파일할때 인터페이스를 코드에서 삭제함즉
interface
는 타입스크립트에게 더 많은 정보를 제공하기 위해 존재
열거형Enum과 리터럴 타입
Enum 타입
Enum
이란 연관된 아이템들을 함께 묶어서 표현 할 수 있는 수단
// enum 선언
enum GenderType {
male,
female
}
interface PersonCard {
readonly n: number
name: string
age: number
gender: GenderType // 기존 gender: string을 수정
address: string
adult: boolean
addComment?:(comment: string) => string
}
let person = {
n: 1,
name: "철수",
age: 31,
gender: GenderType.male, //gender: "남"을 수정
address: "서울",
adult: true
}
function savePerson(person: PersonCard): void {
}
savePerson(person)
위 enum
코드를 자바스크립트 컴파일 된 자바스크립트 코드에서 확인해보면 아래와 같다
enum
속의 아이템 male
의 값은 0
, female
의 값은 1
을 나타낸다.
아이템의 개수가 늘수록 숫자가 늘어나는 방식이다.
이를 숫자 열거형(Numeric Enum)
이라고 한다.
이와 반대로 문자형 열거형(String Enum)
도 존재한다.
// 아래와 같이 enum의 string 값을 할당해주면 된다
enum GenderType {
male = "male",
female = "female"
}
interface PersonCard {
readonly n: number
name: string
age: number
gender: GenderType
address: string
adult: boolean
addComment?:(comment: string) => string
}
let person: PersonCard = {
n: 1,
name: "철수",
age: 31,
gender: GenderType.male,
address: "서울",
adult: true
}
function savePerson(n: number): void {
}
savePerson(person)
String Enum
은 숫자 열거형 처럼 자동 증가하는 기능은 없지만 코드를 실행할 때 읽기 쉬운 값을 주는 장점이 있다.
❗
enum
은interface
와 달리 자바스크립트 코드로 컴파일시 코드가 사라지지 않고 자바스크립트코드에 나타난다.이것은
enum
이 런타임에 존재하는 실체 객체라는걸 나타냄
literal 타입
interface PersonCard {
readonly n: number,
name: string,
age: number,
gender: 'male' | 'female', // |을 이용하여 값을 구분 시켜주면 된다
address: string,
adult: boolean,
addComment?:(comment: string) => string
}
let person: PersonCard = {
n: 1,
name: "철수",
age: 31,
gender: 'male', // 리터럴 타입의 맞춰 수정
address: "서울",
adult: true
}
function savePerson(person: PersonCard): void {
}
savePerson(person)
2. 데이터 타입
any
타입은 어떤 타입이든 가능하게 해준다.
let a: any = 5
a = "a"
a = true
하지만 타입스크립트에서 일반적인 규칙은 타입에 관한 더많은 정보를 명시할 수록 좋다
따라서
any
타입 보다는 좀 더 명시적으로 타입을 정해서 효과적으로 코드를 유지 보수 하는 것이 좋다
유니온 타입
제한된 타입을 동시에 지정해서 사용하고 싶을때 사용한다
let price: number|string = 1000 // `|`를 이용하여 선택적 타입 지정 가능
price = "free"
파이프 라인(|)
을 사용하여 간단하게 타입을 지정할 수 있다.
Type Aliases
만약 위와 같은 조합이 여러개 반복될 경우 같은 코드를 여러번 작성해야할 경우도 있을 것이다
이때 같은 코드를 여러번 반복하는 것 보다는 코드를 타입으로 지정하여 재활용 하는 것이 좋다
이때 Type Aliases
를 사용한다.
type price = number | string; // type 키워드를 사용하여 새로운 타입 선언하는 방법
Type Guard
유니온 타입을 사용할 때 코드 검증을 수행하는 것을 Type Guard
라고 함
type NumOrStr = number | string;
let item: number;
const setItemPrice = (price: NumOrStr): void => {
item = price; // item에서 에러가 발생
// 매개변수 타입이 number와 string이 올 수 있지만 반면에
// item에는 number 밖에 올수 없기 때문에 코드를 고쳐야함
}
setItemPrice(50)
위 코드를 아래와 같이 typeof
연산자와 조건문을 사용하여 변환해 주면 에러를 해결 할 수있다
이 행위를 Type Guard
라고 한다
type NumOrStr = number | string;
let item: number;
const setItemPrice = (price: NumOrStr): void => {
if (typeof price !== "string") item = price;
}
setItemPrice(50)
3. 선택적 매개 변수와 기본 매개변수
타입스크립트에서는 함수에 정의된 모든 매개 변수가 함수에 필요하다고 가정하기 때문에 선언된 함수의 매개변수와 호출된 함수의 인자를 비교하여 수가 일치하지 않으면 에러를 발생한다
// 컴파일 가능한 함수
function chat(who:string, message:string): void {
console.log(`${who}: ${message}`)
}
chat("안녕", "철수")
// 에러 발생
function chat(who:string, message:string): void {
console.log(`${who}: ${message}`)
}
chat("안녕")
// 에러 해결, 선택적 매개변수
function chat(who:string, message?:string): void {
console.log(`${who}: ${message}`)
}
chat("안녕")
❗ 중요
전달되는 매개변수가 여러개이고 이중 몇가지만 선택적 매개변수인 경우
반드시 선택적 매개변수들은 필수 매개변수 뒤에 위치해야한다
위의 마지막 함수처럼 선택적 매개변수를 사용할때 그 값을 찾지 못할 경우 그 값이undefined
가 되는데 매개변수에 default
값을 지정하여 해결할 수있다.
// 선택적 매개변수, 기본 매개변수
// 타입스크립트의 타입 추론 특징을 이용하여 string으로 타입을 명시하지 않아도 된다
function chat(who:string, message? = "guest"): void {
console.log(`${who}: ${message}`)
}
chat("안녕")
// 화살표 함수로 변경
const chat = (who:string, message? = "guest"): void => console.log(`${who}: ${message}`)
chat("안녕")