Typescript

윱니·2023년 12월 12일

1. Javascript의 약점

  • 변수의 타입이 실행 시간에 결정되어 개발자의 실수로 인한 오류가 발생하기 쉽고 찾기도 까다로움 (변수에 잘못된 타입의 값이 할당되어 발생한 오류를 찾기 위해서는 실행 시간에 변수의 값과 타입을 모두 확인해야하는 번거로움이 있음)
  • let, const와 같이 변수/상수를 구분하는 정도의 지워드만 지원되어 약간의 실수로 예상하지 않은 동작이 발생할 수 있음
  • 프로그래머가 마음만 먹으면 객체의 성질을 수시로 변화시킬 수 있음
const obj = { latitude: 11.5, longitude: 47.1 };
const result = obj.latitude * obj.longitute; // 보통은 이런 실수는 컴파일러가 잡아줘야 되는데
console.log(result) // NaN이라는 엉뚱한 값 출현!

2. Typescript가 보완

  • 컴파일 시간에 변수타입을 체크 (VS Code에서 오류캐치도 가능)
  • VS code에 코드를 입력하는 순간 에러메시지 발생
  • 외부 모듈의 타입 정보 제공 (d.ts라는 확장자를 가진 선언파일)

=> 생산성이 향상되고 안전성도 높아진다. 개발 및 유지 보수 과정에서 시간과 노력을 절약할 수 있다.

3. Typescript 입문

1. 컴파일러, tsc

(1) 컴파일러

  • 프로그래밍 언어로 작성된 소스코드 -> 다른 프로그래밍 언어로 변환하는 도구
  • 타입검사, 코드변환
  • 타입스크립트 컴파일러인 tsc는 Typescript -> Javascript코드 변환 해줌
  • 에러메시지 해석할 때 도움
  • 최적화!

(2) tsc 명령어

  • tsc --init : tsconfig.json이 생성되는 명렁어
  • tsc index.ts : index.ts를 컴파일(.ts는 Typescript파일 확장자)
  • tsc src/*.ts : src 디렉토리 안에 있는 모든 Typescript파일을 컴파일
  • tsc index.js --declaration --emitDeclarationOnly : @types 패키지를 위한 .d.ts파일 생성을 하는 명령어(Typescript로 작성된 모듈이 아닌 Javascript로 작성된 모듈에 타입 선언을 제공할 때 유용)

2. tsconfig.json

(1) tsconfig.json

  • tsc --init 명령을 실행하면 생성되는 파일
  • Typescript 프로젝트 설정 파일
  • 프로젝트의 컴파일 옵션 및 입력 파일들을 정의

(2) tsconfig.json 주요 옵션

  • compilerOptions - target 옵션
    • 해당 Typescript 프로젝트 내 코드들이 어떤 Javascript 버전으로 변환을 할 지 정하는 옵션
  • compilerOptions - module 옵션
    • Typescript 파일을 컴파일한 후 생성되는 Javascript 모듈의 형식을 지정
    • target 옵션과는 서로 독립적인 관계니 프로젝트의 요구사항에 따라 옵션을 설정하면 됨
  • compilerOptions - outDir 옵션
    • 컴파일 된 Javascript 파일이 저장될 출력 디렉터리를 지정
    • 예를 들어, "outDir": "dist"로 설정하면 컴파일된 파일들이 dist 폴더에 저장됨
    • compilerOptions - strict : 엄격한 타입 검사 옵션을 모두 활성화하는 옵션 (당연하게도, true로 설정하는 것 권장!!)
  • compilerOptions - sourceMap 옵션
    • 컴파일 된 Javascript 파일에 대한 소스 맵을 생성하는 옵션
    • 소스 맵을 사용하면 실행중에 에러가 발생했을 때 원래 Typescript 소스 코드의 위치를 확인할 수 있음
    • 코드 디버깅에 매우 큰 도움이 되기 때문에 개발환경에서는 꼭 true로 설정하는 것 권장!
  • include, exclude 옵션
    • tsc가 컴파일을 할 때 포함하거나 제외할 파일이나 디렉터리를 지정하는 옵션

3. .d.ts

  • Typescript는 @types 라이브러리를 통해 외부 라이브러리에 대한 타입 정보를 제공 (.d.ts 파일이 많이 있음)
  • .d.ts 파일은 Typescript 타입 정의 파일 (Javascript 라이브러리에 대한 타입 정보를 제공)
  • .d.ts 파일로 Typescript 컴파일러는 외부 라이브러리의 함수 타입정보, 외부 라이브러리 클래스 타입정보, 외부 라이브러리 객체 타입정보, 외부 라이브러리의 타입추론을 할 수 있음 (타입추론이란, 타입이 명시되지 않았을 때 컴파일러가 알아서 해당 타입에 대해 추론을 하는 것)

4. Typescript 기본 타입

1. 기본 타입

(1) boolean

  • 2가지의 상태를 표현 -> boolean
  • 3가지 이상의 상태를 표현 -> enum이나 string

(2) number

  • Typescript에서 사용하는 모든 숫자

(3) string

  • 텍스트 데이터
  • 작은따옴표('), 큰따옴표("), 백틱(`)

(4) 배열

  • 기본 타입에 []가 붙은 형태의 타입

(5) 튜플(tuple)

  • 서로 다른 타입의 원소를 순서에 맞게 가질 수 있는 특수한 형태의 배열
const person: [string, number, boolean] = ['Spartan', 25, false];
const person2: [string, number, boolean] = [25, 'Spartan', false]; // 오류!

(6) enum

  • 열거형 데이터 타입
  • 명확하게 관련된 상수 값들을 그룹화하고자 할 때
  • enum 안에 있는 각 요소는 값이 설정되어 있지 않으면 기본적으로 숫자 0으로 시작
  • enum 안에 있는 요소에는 number 혹은 string 타입의 값만 할당 가능
enum UserRole {
  ADMIN = "ADMIN",
  EDITOR = "EDITOR",
  USER = "USER",
}

enum UserLevel {
  NOT_OPERATOR, // 0
  OPERATOR // 1
}

function checkPermission(userRole: UserRole, userLevel: UserLevel): void {
  if (userLevel === UserLevel.NOT_OPERATOR) {
    console.log('당신은 일반 사용자 레벨입니다');
  } else {
    console.log('당신은 운영자 레벨입니다');
  } 

  if (userRole === UserRole.ADMIN) {
    console.log("당신은 어드민입니다");
  } else if (userRole === UserRole.EDITOR) {
    console.log("당신은 에디터입니다");
  } else {
    console.log("당신은 사용자입니다");
  }
}

const userRole: UserRole = UserRole.EDITOR;
const userLevel: UserLevel = UserLevel.NOT_OPERATOR;
checkPermission(userRole, userLevel);

2. const, readonly

  • const와 readonly는 불변성을 보장

(1) let

  • let 키워드를 사용하여 선언하면 변수 (값을 변경할 수 있음)

(2) const

  • const 키워드를 사용하여 선언하면 변수가 아닌 상수 (값을 변경할 수 없음 = 연산자로 다시 할당 불가능)

(3) readonly

  • Typescript에서 등장한 키워드
  • Typescript에서 객체의 속성을 불변으로 만드는데 사용됨
class Person { 
  readonly name: string;
  readonly age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

const person = new Person('Tom', 30);

console.log(person.name);  // 출력: 'Tom'
console.log(person.age);   // 출력: 30

person.name = 'Jane';  // 에러: 'name'은 readonly 속성이므로 다시 할당할 수 없음
person.age = 25;       // 에러: 'age'은 readonly 속성이므로 다시 할당할 수 없음

=> readonly를 const로 치환?
안됨!! const 키워드는 일반 변수를 상수화 할 때 사용하는 것!

3. any, unknown, union

  • 어쩔 수 없이 가변적인 타입의 데이터를 저장하고 싶다면 any 보다는 unknown을 사용!
  • 가변적인 타입을 일일이 정의할 수 있다면 union 사용이 가장 나음!

(1) any

  • 모든 타입의 슈퍼타입 (어떤 값이든 저장가능)
  • Typescript 사용하는 주된 이유 중 하나가 프로그램의 타입 안정성을 확보하기 위해서인데 any의 사용은 코드의 안정성과 유지 보수성을 저해할 수 있음 (가급적 사용하지 않아야 함)

(2) unknown

  • any와 비슷하지만 더 안전한 방식
  • 모든 타입의 값을 저장할 수 있지만 그 값을 다른 타입의 변수에 할당하려면 명시적으로 타입을 확인해야 함
let unknownValue: unknown = '나는 문자열입니다!';
let stringValue: string;

if (typeof unknownValue === 'string') {
  stringValue = unknownValue;
  console.log('unknownValue는 문자열이네요');
} else {
  console.log('unknownValue는 문자열이 아니었습니다');
}

(3) union

  • unknown 타입도 결국 재할당이 일어나지 않으면 타입 안전성이 보장되지 않음
  • union은 여러타입중 하나를 가질 수 있는 변수를 선언할 때 사용
  • | 연산자를 사용하여 여러 타입을 결합하여 표현
type StringOrNumber = string | number; // 원한다면 | boolean 이런식으로 타입 추가가 가능!

function processValue(value: StringOrNumber) {
  if (typeof value === 'string') {
    // value는 여기서 string 타입으로 간주됨
    console.log('String value:', value);
  } else if (typeof value === 'number') {
    // value는 여기서 number 타입으로 간주됨
    console.log('Number value:', value);
  }
}

processValue('Hello');
processValue(42);

=> Typescript를 쓰면서 여러 타입을 하나의 변수로 해결하겠다는 생각은 가급적 지양!

profile
코린이 탈출을 기원하는 코린이

0개의 댓글