[TypeScript] 타입스크립트에 대하여(작성중)

82.831·2023년 1월 12일
0

https://joshua1988.github.io/ts/guide/basic-types.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85
https://typescript-kr.github.io/pages/tutorials/ts-for-the-new-programmer.html
https://react.vlpt.us/using-typescript/
의 글들을 바탕으로 학습을 위해 해당 문서를 작성하였습니다.


타입스크립트란?

  • 타입스크립트는 자바스크립트에 타입을 부여한 언어이다. 자바스크립트의 확장된 언어라고 볼 수 있다. 타입스크립트는 자바스크립트와 달리 브라우저에서 실행하려면 파일을 한번 변환해줘야 하는데, 이 변환 과정을 컴파일(complile) 이라고 부른다.
  • TypeScript의 목표는 JavaScript 프로그램의 정적 타입 검사자이다. 즉, 코드가 실행되기 전에 실행하고(정적), 프로그램 타입이 정확한지 확인하는 도구(타입 검사)이다.
  • 브라우저가 타입스크립트가 아닌 자바스크립트를 이해하기 때문에, 타입스크립트는 컴파일 시에 자바스크립트로 변환된다.
    - 타입스크립트에 에러가 있을 경우 자바스크립트로 변환되지 않는다.

왜 타입스크립트를 사용할까?

타입스크립트는 아래 두가지 관점에서 자바스크립트 코드의 품질과 개발 생산성을 높일 수 있다.

  1. 에러 사전 방지
  • 자바스크립트의 경우

    function add(a, b){
    	return a+ b;
    }

    우리는 아래와 같이 add라는 함수를 통해 숫자 a와 숫자 b를 더한 반환 값(정수)을 얻으려 한다.

    add(1, 2); // 3

    하지만, 자바스크립트에서는 아래와 같은 경우 사용자에게 에러를 발생하지 않으며 정상 작동하는 것을 볼 수있다.

    add(); // NaN
    add(1); // NaN
    add('12', '34'); // 1234
  • ✔️ 타입스크립트의 경우

    function add(a: number, b: number) {
      return a + b;
    }
    add('10', '20'); // Error: '10'은 number에 할당될 수 없습니다.

    하지만, 타입스크립트의 경우 type을 설정하여 위와 같이 의도하지 않은 코드의 동작을 예방할 수 있다.

  1. 코드 자동 완성과 가이드
    프론트엔드 개발을 할 때 가장 많이 사용되는 Visual Studio Code는 툴의 내부가 타입스크립트로 작성되어 있어 타입스크립트로 코드를 작성할 때 개발 툴의 기능을 최대로 활용할 수 있도록 최적화되어 있다.
  • TypeScript는 변수에 대한 타입이 지정되어 있기 때문에 VSCode에서 해당 타입에 대한 API를 미리 보기로 띄워줄 수 있고 따라서, API를 다 일일이 치는 것이 아니라 빠르고 정확하게 작성해나갈 수 있다.
  • TypeScript 를 사용하면 함수를 사용 할 때 해당 함수가 어떤 파라미터를 필요로 하는지, 그리고 어떤 값을 반환하는지 코드를 따로 열어보지 않아도 알 수 있다.
  • 추가적으로, 리액트 컴포넌트의 경우 해당 컴포넌트를 사용하게 될 때 props 에는 무엇을 전달해줘야하는지, JSX 를 작성하는 과정에서 바로 알 수 있으며, 컴포넌트 내부에서도 자신의 props 에 어떤 값이 있으며, state 에 어떤 값이 있는지 알 수 있어서 편리하다.

기본 타입

Boolean

let isLoggedIn: boolean = false;

Number

let num: number = 10;

String

let str: string = 'hi';

Object

declare function create(o: object | null): void;

create({ prop: 0 }); // 성공
create(null); // 성공

create(42); // 오류
create("string"); // 오류
create(false); // 오류
create(undefined); // 오류

Array

let arr: number[] = [1,2,3];

또는 제네릭

let arr: Array<number> = [1,2,3];

Tuple (배열의 길이가 고정되고, 각 요소의 타입이 지정되어 있는 배열 형식)

let arr: [string, number] = ['hi', 10];
// 첫번째는 string 두번째는 number 타입의 배열 형식이다.
let arr: [string, number, boolean] = ['hi', 10, true];
// 첫번째는 string 두번째는 number 세번째는 boolean 타입의 배열 형식이다.
arr[0] = 1; // error. string 타입의 index를 number 타입으로 변경하려고 시도

Enum (특정 값(상수)들의 집합)

enum Color {Red, Green, Blue}
let c: Color = Color.Green;
  • Enum은 인덱스 번호로도 접근할 수 있다.
    기본적으로 enum은 0부터 시작하여 멤버들의 번호를 매기는데, 멤버 중 하나의 값을 수동으로 설정하여 번호를 바꿀 수 있다.
    예를 들어, 위 예제를 0 대신 1부터 시작하게 하여 번호를 매기도록 바꿀 수 있다.
enum Color {Red = 1, Green, Blue}
let c: Color = Color.Red;

모든 값을 수동으로 설정할 수도 있다.

enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
  • 매겨진 값을 사용해 enum 멤버의 이름을 알아낼 수도 있다.
    예를 들어, 위의 예제에서 2라는 값이 위의 어떤 Color enum 멤버와 매칭되는지 알 수 없을 때, 아래와 같이 이에 일치하는 이름을 알아낼 수 있다.
enum Color {Red = 1, Green, Blue}
let colorName: string = Color[2] // Green. Red는 index 1부터 시작
  • Enum은 양방향 매핑이 되어있다.
enum OS = {
	Window = 3,
    Ios = 10,
    Android
}
console.log(Os['Ios']); // 10
console.log(Os[10]); // Ios

Any
단어 의미 그대로 모든 타입에 대해서 허용한다.
Typescript의 보호장치들을 완전히 비활성화 시킨다.

any 타입은 타입의 일부만 알고 전체는 알지 못할 때 유용하다.
예를 들어, 아래와 같이 여러 다른 타입이 섞인 배열을 다룰 수 있다.

let list: any[] = [1, true, "free"];
list[1] = 100;

Void
변수에는 undefined와 null만 할당하고, 함수에는 반환 값을 설정할 수 없는 타입

let unuseful: void = undefined;
function notuse(): void {
  console.log('sth');
}

Null, Undefined
undefined 과 null 둘 다 각각 자신의 타입 이름으로 undefined, null로 사용한다. void처럼 그 자체로 유용한 경우는 거의 없다.

// 이 밖에 이 변수들에 할당할 수 있는 값이 없다!
let u: undefined = undefined;
let n: null = null;

Never
함수의 끝에 절대 도달하지 않는다는 의미
1. 에러를 반환하거나

function showError():never{
	throw new Error();
}
  1. 영원히 끝나지 않거나
function infLoop():never{
	while(true){
    	// do something...
    }
}

읽기 전용

type Player = {
	readonly name: string, // 읽기 전용
    age?: number // ?는 필수가 아님을 뜻함
}

const playerMaker = (name:string) : Player => ({name})
const nico = playerMaker("nico")

nico.name = "las" // error

Function

Call Signatures

직접 타입을 생성하여 함수가 어떻게 동작하는지 서술 해 둘 수 있다.

type Add = (a:number, b:number) => number;

const add:Add = (a, b) => a + b;

Polymorphism (다형성)

Generics (제네릭)

  • 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미한다.
type SuperPrint = {
	<T>(arr: T[]): T
}

const superPrint: SuperPrint = (arr) => arr[0];

const a = superPrint([1, 2, 3, 4]); // a는 number type
const b = superPrint([true, true, false]); // b는 boolean type

이처럼 함수를 호출할 때 넘긴 타입에 대해 타입스크립트가 추정할 수 있게 된다. 따라서, 함수의 입력 값에 대한 타입과 출력 값에 대한 타입이 동일한지 검증할 수 있게 된다.

인자와 반환 값에 여러가지 타입을 허용하기 위해 아래와 같이도 작성할 수 있다.

function logText(text: any): any {
  return text;
}

하지만, any라는 타입은 타입 검사를 하지 않기 때문에 함수의 인자로 어떤 타입이 들어갔고 어떤 값이 반환되는지는 알 수가 없게 된다. 이것이 제네릭을 사용하는 이유이다.

type SuperPrint = {
	<T>(arr: T[]): T
}

const superPrint: SuperPrint = (arr) => arr[0];

👇 다른 선언 방법

function superPrint<T>(arr: T[]) {
	return arr[0];
}

0개의 댓글