WEB/TypeScript

[TypeScript] 타입스크립트, 타입 종류 (tsconfig.json)

devOhzl 2024. 8. 6. 23:45

타입스크립트란

정적 타입컴파일 언어

  • 자바스크립트 (동적 타입) : 런타임에서 동작할 때 타입 오류 확인
  • 타입스크립트 (정적 타입) : 코드 작성 단계에서 타입 오류 확인

브라우저나 Node.js 환경은 타입스크립트가 직접적으로 동작할 수는 없다.

👉 자바스크립트로 변환(컴파일) 후 브라우저나 Node.js 환경에서 동작

tsconfig.json

{
  "compilerOptions": {
      "target" : "ES2015",
      "module": "ESNext",
      "moduleResolution": "Node",
      "esModuleInterop": true,
      "lib" : [ "ESNext", "DOM" ],
      "strict": true
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

📌 compilerOptions

타입스크립트를 자바스크립트로 변환하기 위해 어떤 옵션이 세부적으로 필요한지 결정해주는 옵션

target : "ES2015"  컴파일 될 ES(JS) 버전 명시 ES2015년도 버전 권장
module: "ESNext" 모듈 시스템 지정 ( CommonJS, AMD, ESNext) - nodeJS에서는 CommonJS Js의 표준 명칭인 ECMAScript의 가장 최신 버전으로 브라우저에서 사용하는 ESNext 모듈을 사용
moduleResolution: "Node" 모듈 해석 방식 지정 ( Node, Classic ) 어떤 경로를 작성할 떄 특정 폴더에 있는 index 이름을 가지는 js 파일은 선언 생략 가능
esModuleInterop: true ESM 모듈 방식 호환성 활성화 여부
( 기본 false )
js의 ECMAScript , 즉 ESM 방식을 사용하고 있는데 Node.js 는 common.js 방식을 사용한다.
👉 ESM 방식 + common.js 방식을 호환해서 전부 사용할 수 있는 구조로 변경
lib : [ "ESNext", "DOM" ]  컴파일에서 사용할 라이브러리 지정 ts가 js로 코드를 컴파일할 때 내부적으로 사용해야하는 라이브러리 목록 지정
strict: true  더 엄격한 타입 검사 활성화 ts 문법을 엄격하게 사용 👉  정적 타입인 ts 언어를 쓰는 의미가 명확해짐

 

📌 ESM vs CommonJS

// common.js
// ESM 방식이 아닌 Node.js에서 사용하는 CommonJS 방식으로 생성
const ohzl = {
	name: 'ohzl',
    age: 27
}

module.exports = { ohzl }

 

- CommonJS 방식

esModuleInterop 옵션을 끄게 되면 CommonJS 방식만 사용하므로 기본 내보내기 개념이 존재하지 않아서 사용할 수 없다.

import * as commonjs from './common'

 

옵션을 활성화해야 CommonJS 방식으로 export한 문법을 ESM 문법으로 사용 가능하다.

import commonjs from './common'

 

 

📌 include

어떤 타입스크립트 파일들을 컴파일해서 자바스크립트로 변환할 것인지,

즉 그 컴파일할 파일에 대한 경로가 어디에 있는지 배열 데이터로 목록화해서 제공

src/**/*.ts 현재 파일 주변에 있는 src 폴더에 모든 하위 경로를 포함해서 모든 이름의 ts 파일을 포함

 

📌 exclude

타입스크립트 컴파일에서 제외할 파일 경로 목록

node_modules 패키지를 보관하기 위한 용도이므로 js로 변환할 필요가 없음

 

타입 종류

데이터 할당이 되지 않으면 undefined로 초기 세팅이 되므로, 나중에 값 할당을 해줘야한다.

 

1️⃣ 문자

let str : string
let red : string = "Red"

 

2️⃣ 숫자

let num: number
let float: number = 3.14
let nan: number = NaN

 

3️⃣ 불린

let isBoolean: boolean
let isDone: boolean = false

 

4️⃣ Null / Undefined

let nul: null
let und: undefined

console.log(nul)	// undefined
console.log(und)	// undefined

 

null은 null로 재할당 해줘야하는데, 가동성이 좋지 않음

null / undefined는 잘 쓰이지 않는다.

 

5️⃣ 배열

const fruits: string[] = ['Apple', 'Banana']
const numbers: number[] = [1,2,3,4]
const union: (string|number)[] = ['Apple', 1, 2, 'Banana', 3, 4]

 

6️⃣ 객체

// typeof DATA = 'object'
const obj: object = {}
const arr: object = []
const func: object = function() { }

 

객체 뿐만 아니라 배열, 함수도 'object' 타입이 되므로 타입이 엄격해지지 않는다.

 

const userA: {
     name: string,
    age: number,
    isValid: boolean
} = {
	name: 'ohzl',
    age: 27,
    isValid: true
}

 

객체 데이터의 type을 명시할 때는 object 타입을 직접적으로 사용하지는 않고,

객체 속성의 타입을 각각 명시해서 사용한다.

 

interface User {
	name: string
    age: number
    isValid: boolean
}

const userA: User = {
	name: 'ohzl',
    age: 27,
    isValid: true
}

const userB: User = {
	name: 'ohzl2',
    age: 30,
    isValid: false
}

객체 데이터는 속성과 값에 key-value 형태로 존재를 하는데,

같은 타입의 새로운 객체를 만들 때마다 타입을 지정해야하는 상황이 생길 수도 있다.

그 때, Interface를 통해 손쉽게 재활용 한다.

 

7️⃣ 함수

const add: (x: number. y: number) => number = function (x, y) {
	return x + y
}

const add = function (x: number. y: number): number {
	return x + y
}

const a: number = add(1, 2)

매개변수의 타입을 지정해주고 반환되는 값의 타입을 지정해준다.

const hello: () => void = function () {
	console.log('Hello world')
}

const hello = function (): void {
	console.log('Hello world')
}

const h: void = hello()

return 키워드가 없는 함수를 호출하면 undefined가 반한되므로 반환 값에는 void 타입을 지정한다.

 

8️⃣ Any

let hello: any = 'Hello world'
hello = 123
hello = false

모든 데이터 타입을 사용할 수 있다. 엄격성이 떨어지므로 사용을 지양한다.

9️⃣ Unknown

const a: any = 123
const u: unknown = 123

const any: any = a // 또는 u
const boo: boolean = a 	// 또는 u --> error
const num: number = a	// 또는 u --> error
const arr: string[] = a	// 또는 u --> error
const obj: { x: string, y: number } = a	// 또는 u --> error

Any타입은 어떤 데이더튼 할당해도 상관없지만,  

Unknown은 정확하게 어떤 데이터가 할당될지 알 수가 없으므로 '알 수 없음'으로 표시하겠다는 의미를 가진다.

 

위 코드처럼 any 타입인 a 를 할당하면 아래 재할당 코드에서 문제가 없지만

unknown 타입인 u를 할당하면 알 수 없는 타입의 데이터가 재할당되므로 타입에러가 발생한다.

🔟 Tuple

const tuple: [string, number, boolean] = [ 'a', 1, false ]
const tuple: [string, number, boolean] = [ 'a', 1, false, 123 ] // error !

배열의 정확한 아이템 개수와 순서를 명시를 하는 타입

배열 데이터의 개수가 달라질 수 있는 구조에서는 적합하지 않다.

 

const users: [number, string, boolean][] 
 = [[1, 'Neo', true], [2, 'Evan', false'], [3, 'Lewis', true]]

배열 데이터이지만 Tuple 타입이다.

배열 아이템의 개수와 순서를 정확하게 지정한다.

1️⃣ 1️⃣ Void

function hello(msg: string): void {
	console.log(`Hello ${msg}`)
}

const hi: void = hello('world')

return 키워드를 사용하지 않으면 데이터는 undefined가 반환되지만,

타입스크립트에서는 void 타입을 사용해야 return 키워드가 없는 함수라고 해석된다.

👉 return 키워드를 명시하지 않은 함수에서 반환되는 타입

1️⃣ 2️⃣ Never

const nev: [] = []		// --> 배열에 타입을 선언해주지 않으면 never로 인식되어 아무런 값도 할당할 수 없음
nev.push(3) // error !

아무것도 할당할 수 없는 구조

직접 사용할일은 거의 없다.

1️⃣ 3️⃣ Union

let union: string|number
union = 'Hello Type'
union = 123
union = false // error

타입을 여러개 지정할 수 있으며, 여러개 사용 가능하다.

1️⃣ 4️⃣ Intersection

interface User {
	name: string,
    age: number
}

interface Validation {
	isValid: boolean
}

const obj: User & Validation = {
	name: 'Neo',
    age: 20,
    isValid: true
}

인터페이스의 타입이 동시에 지정이 된다.