brunch

You can make anything
by writing

C.S.Lewis

by 훈오빵 Nov 26. 2023

Typescript 공부(1)

I. Typescript 소개

- Typescript : Javascript에 Type을 추가해 기존 JS의 결핍을 채워주는 JS로 Compile되는 언어. Type을 검사하는 정적 타입 검사기이자 컴파일의 결과가 JS로 컴파일되는 언어로 .ts 확장자 사용

- MS가 개발해 2012년 0.8버전을 오픈소스로 공개. 2023년 현재 대부분의 text-editor에서 지원하며, 수많은 JS 관련 프로그램들이 TS를 기반으로 작성되고 있음.


1. 이점

1) Compile 시점에 에러 확인 가능

2) 개발 툴에서 개발자에게 상대적으로 더 많은 도움을 줄 수 있음. ex) 코드 자동완성 기능

function add(a, b) {
    return a + b;
}
add(1, 2) // 3을 반환
add("1", "2") // 12를 반환
---------------------------------------------------------
function add(a: number, b: number) {
    return a + b;
}
add(1, 2) // 3을 반환
add("1", "2") // 컴파일 에러


2. Playground에서 실행하기

- Typescript 공식 웹사이트에서 TS 작성 및 실행을 할 수 있는 환경 제공

https://www.typescriptlang.org/play


3. Node Runtime에서 실행하기

$ npm install -g typescript
$ tsc --version
$ cd project-dir
$ tsc --init
// hello-ts.ts

const message = "Hello world";
console.log(message);

-------------------------------------------------------
// hello.ts.js 자동으로 생성됨
var message = "Hello world";
console.log(message);
-------------------------------------------------------
$ node hello-ts.js 


4. ts-node로 실행하기

- Compile 과정 없이 바로 실행하기 위해 ts-node 패키지 설치

$ npm install -g ts-node
$ ts-node hello-ts.ts





II. 기초문법 : type이 있다는 점 외 JS와 동일


1. 변수 선언

- 방법 : var, let, const

function foo( ) {
    if (true) {
        var a = 10;
    }
    return a;
}

console.log(foo( ));

// 결과
// 10

** if문 블록 안 변수 a를 블록 밖에서 리턴했음에도 불구하고 결과가 콘솔에 출력됨
** var는 함수 영역 내 어디서든 접근할 수 있음
** 이러한 이유로 최근에는 let과 const를 주로 사용함

function bar( ) {
    if (true) {
        let a = 10;
    }
    return a;
}

console.log(bar()); // 변수 a가 없는 에러 발생

** let은 block scope로 동작
** let은 변수값을 변경할 수 있고, const는 변경할 수 없음

let a = 10;
a += 1;
console.log(a); // 11출력

const b = 10;
b +=1;
console.log(b) // 에러 출력

** const에 값을 재할당 할 수 없다고 해서 불변은 아님. 할당한 변수에서 변경할 수 없는 것은 해당 변수의 메모리 주소 값(레퍼런스) 이며, const에 배열이나 객체 등을 할당하면 값을 변경할 수 있음.


2. Type annotation : type을 명시하는 법

let username: string = "Hoon";                // 문자열
let height: number = 175;                         // 숫자
let isConditionGood: boolean = true;    // Boolean
// 함수의 매개변수와 결과값에 타입을 선언하는 법

function printMessage(message: string): void {
    console.log(message);
}
// 객체에 타입을 선언하는 법

let myInfo : {name: string; height: number; isConditionGood: boolean } =
{ name: "Hoon",
height: 175,
isConditionGood: true,
};
// 선택적 속성 optional property

let myInfoWithGender: {
    name: string;
    height: number;
    isConditionGood: boolean;
    gender?: string;         // 선택적 속성
} = {
    name: "Hoon",
    height: 175,
    isConditionGood: true,
};


// 함수의 매개변수의 선택적 속성

function printMessageWithAlert(message: string, isCritical?: boolean): void {
    console.log(message);

    if (isCritical) {
        alert(message);
    }
}


3. 기본 Type 7종

- type(자료형)은 변수가 어떤 형식의 값을 갖는지 나타냄

1) null : 의도적으로 값이 없음을 나타낼 때 사용

2) undefined : 변수에 값이 할당도지 않은 경우, 즉 의도하지 않은 값의 부재 의미

3) boolean : true or false

4) string : 문자열

5) number : 정수, 부동소수점, 16진수, 8진수 등 숫자

6) bigint : 매우 큰 숫자 할당 가능한 타입. 숫자 뒤에 n을 붙여서 표시

7) symbol : 불변이면서 유니크한 값을 표현

const one: number = 1;                         // number
const myName: string = "Hoon";        // string
const trueOrFalse: boolean = true;    // boolean
const unIntended: undefined = undefined; // undefined
const nullable: null = null;                 // null
const bigNumber: bigint = 1234567890123456789012345678901234567890n;        // bigint
const symbolValue: symbol = Symbol("symbol");    // symbol

console.log(one + 1);     // 2
console.log(myName + " is my name");        // Hoon is my name
console.log(trueOrFalse ? "true" : "false");     // true
console.log(bigNumber / 10000000000000000n);    // 123456789012345678901234n

// 모든 값이 유일하므로 같은 값을 넣어도 false
console.log(symbolValue === Symbol("symbol"));


4. 배열과 튜플 Array & Tuple

- 데이터를 여러 개를 넣는다는 점에서 배열과 튜플은 유사하나, 배열은 크기가 고정이 아니고 튜플은 고정.

- 배열은 각 원소의 타입을 정의하고, 튜플은 원소 개수 만큼 타입을 정의해야 함

const numbers: number[] = [1, 2, 3, 4, 5];                            // 숫자 배열
const stringArray: Array<string> = ["a", "b", "c", "d", "e"]   // 문자열 원소

// 스프레드 연산자로 합치기 가능
const oneToTen = [...numbers, ...numbers2];
console.log(...oneToTen);

// 객체의 배열 타입
const idols: { name: string; birth: number}[ ] = [
    { name: "minji", birth: 2004 },
    { name: "hani", birth: 2004 },
    { name: "haerin", birth: 2006 },
];

// 배열의 원소가 객체인 타입
const gameConsoleArray: Array<{ name: string; launch: number }> = [
    { name: "PS5", launch: 2020 ],
    { name: "Nintendo Switch", launch: 2017 },
];
// 튜플은 원소 개수만큼 타입 정의 필요
const myTuple: [string, number] = ["Hoon", 175];

// 튜플은 함수의 매개변수가 여러개일 때 유용
function printMyInfo(label: string, info: [string, number]): void {
    console.log(`[${label}]`, ...info);
}

// 결과값 : [튜플 테스트] Hoon 175
printMyInfo("튜플 테스트", myTuple);

// 튜플을 반환하는 함수
function fetchUser(): [string, number] {
    return ["Hoon', 175];
}

// 결과값을 분해해서 받을 수 있음
const [name24, height24] = fetchUser( );
console.log(name24, height24);


5. any, void, never

let anyValue = 10; // number 타입으로 추론
anyValue = "hello"; // 컴파일 에러
anyValue = true; // 컴파일 에러
-------------------------------------------------------
let anyValue: any = 10;
anyValue = "hello";
anyValue = true;

**any type : 타입을 모르거나 지정할 수 없을 때 컴파일 에러를 피하기 위해 사용 가능
// 결과값이 없음
function print(value: any): void {
    console.log(value);
}

// 예외를 던짐
function throwError(message: string): never {
    throw new Error(message);
}

// 무한 루프
function infiniteLoop(): never {
    while (true) {}
}

** void/never : 함수의 반환값에 지정하는 타입. void는 함수의 결과값이 없을 때 사용, never는 의도적으로 값을 반환하지 않는 때 사용. 예외를 발생시키는 함수이거나 무한루프를 실행하는 함수가 이에 해당됨.


6. union, narrowing

let anyValue: number | string | boolean = 10;        //이 시점에서는 number
anyValue = "hello";         // string
anyValue = true;            // boolean

** union type은 변수 하나에 두 개 이상의 타입을 지정하는 것으로 "|" 기호로 타입을 구분.
let anyValue: number | string | boolean = 10;
printAny(anyValue);
anyValue = "hello";
printAny(anyValue);
anyValue = true;
printAny(anyValue);

// 매개변수로 number, string, boolean을 할당할 수 있음
function printAny(value: number | string | boolean): void {
    if (typeof value === "number") {
        console.log(value.toExponential(3));
    } else if (typeof value === "string") {
        console.log(value.toUpperCase());
    } else if (typeof value === "boolean") {
        console.log(value ? "참" : "거짓");
    }
}

** Narrowing은 말 그대로 타입의 범위를 좁히는 것. type guard(typeof, instanceof, in 등)를 사용해 값 할당 또는 조건문으로 검사해 타입을 좁힘.


7. Type 별칭

- 자주 재사용하는 유니온 타입의 경우 타입 별칭을 사용하면 편리. 타입 별칭은 type 키워드를 사용해 정의

type nsb = number | string | boolean;

- 이미 만든 타입에 추가로 타입을 넣어더 다시 별칭을 만드는 것도 가능

type nullableNsb = nsb | null | undefined
// 타입 별칭
type nsb = number | string | boolean;

let anyValue: nsb = 10;
anyValue = "hello";
anyValue = true;
anyValue = null;    // 컴파일 에러

// 타입 별칭에 null, undefined 추가
type nullableNsb = nsb | null;

let nullableValue: nullableNsb = null;
nullableValue = 20;
nallableValue = "nullable";
nullableValue = false;
nullableValue = undefined;        // 컴파일 에러


8. Intersection type

- A이면서 B인 타입을 정의. 기호도 "&"로 사용

type 타입명 = {
    속성명: 타입;
}
type cup = {
    size: string;
};

type brand = {
    brandName: string;
};

type brandedCup = cup & brand;        // cup이면서 brand가 있는 타입

let starbucksGrandeSizeCup: brandedCup = {
    brandName: "스타벅스",
   size: "grande",
};


9. Literal type

- 기본 타입의 값들을 조합해서 한정적인 값들만 나타내는 타입을 만들 수 있음.

type CoffeeSize = "small" | "medium" | "large";

let myCoffeeSize: CoffeeSize = "small";
let starbucksCoffeeSize: CoffeeSize = "tall";     // 타입 에러


10. Function type

- JS와 TS에서는 함수를 값처럼 사용할 수 있음. 즉 어떤 변수에 함달된 값이 함수라면 그 타입은 함수 타입.

function echo(message: string): string {
    console.log(message);
    return message;
}

const funcEcho = echo;    // 함수를 값에 할당
type = FuncEcho = (message: string) => string;
const funcEcho2: FuncEcho = echo;

** 함수타입을 타입 별칭으로 지정할 수도 있음
type FuncEcho3 = {
   (message: string): string;        // => 가 없는 것에 주의
};
const funcEcho3: FuncEcho3 = echo;
funcEcho3("test3");        // 함수의 타입을 자동으로 추론해 실행
funcEcho3(123);             // 매개변수가 문자열이 아니므로 타입 에러


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari