Typescript 기초

따봉도치 개발자·2023년 5월 30일
0

TypeScript 프로젝트 환경

1. TypeScript 프로젝트 환경 구성하기

프로젝트 폴더를 생성 -> 프로젝트 폴더 안으로 이동 -> 터미널에서 npm init -y 명령어 실행 -> 새로운 프로젝트를 초기화 -> npm install typescript --save-dev -> 프로젝트 루트 디렉토리에 tsconfig.json 파일을 생성 -> 밑의 내용을 붙이기 { "compilerOptions": { "target": "es6", "module": "commonjs", "sourceMap": true, "outDir": "./dist" }, "include": [ "src/**/*" ] } -> src 폴더에 index.ts

2. TypeScript ESLint와 Prettier 설정하기

VSCode의확장 프로그램인 ESLint를 설치 -> 이동하는 커맨드는 cmd + shift + p -> { // ... "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "eslint.alwaysShowStatus": true, "eslint.workingDirectories": [ {"mode": "auto"} ], "eslint.validate": [ "javascript", "typescript" ], } 붙여넣기 -> 마지막으로 VSCode 에디터 설정 중 format on save가 설정되어 있는지 확인 후 체크 해제

3. 필요한 프리셋과 라이브러리를 설치

npm i -D @babel/core @babel/preset-env @babel/preset-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint prettier eslint-plugin-prettier

4. 프로젝트 폴더 밑에 .eslintrc.js 파일을 만들고 밑에 내용 붙여넣기

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true,
    jest: true,
  },
  extends: [
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  plugins: ['prettier', '@typescript-eslint'],
  rules: {
    'prettier/prettier': [
      'error',
      {
        singleQuote: true,
        tabWidth: 2,
        printWidth: 80,
        bracketSpacing: true,
        arrowParens: 'avoid',
      },
    ],
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    'prefer-const': 'off',
  },
  parserOptions: {
    parser: '@typescript-eslint/parser',
  },
};

TypeScript 타입

1.Boolean(불리언) 타입

let isShow: boolean = true;
let isDone: boolean = false;

2. Number(숫자) 타입

let number1: number = 5;
let number2: number = 0.7;

3.String(문자열) 타입

let firstName: string = "coding";
let lastName: string = 'kim';
let longString: string = `Kimcoding is a developer.
He is 20 years old.`

4. Array(배열) 타입

//첫 번째 방법
let items: string[] = ["apple", "banana", "grape"];

//두 번째 방법
let numberList: Array<number> = [4, 7, 100];

5.Tuple(튜플) 타입

let user: [string, number, boolean] = ["kimcoding", 20, true];
console.log(user[2].toString());

6.Object(객체) 타입

let user: {name: string, age: number} = {
	name: "kimcoding",
	age: 20
}

7.Any 타입

클라이언트에서 유저로부터 받은 데이터에서 들어오는 값인 경우 알지 못하는 타입일 수 있는데, 타입 검사를 하지 않고자 할 때 any 타입을 사용할 수 있다.

let obj: object = {};

//에러가 납니다.
obj = "hello";

let maybe: any = 4;

//정상적으로 동작합니다.
maybe = true;

엄격한 타입 검사를 진행하지 않기 때문에, 실제 할당된 값이 가지지 않는 메서드 및 프로퍼티로 접근해도 에러가 나지 않는다.대신, 실제 할당된 값이 가지지 않는 메서드 및 프로퍼티이기 때문에 반환되는 값은 undefined이다.

let maybe: any = 4;

//undefined로 출력됩니다.
console.log(maybe.length);

any타입은 타입의 일부만 알고, 전체는 알지 못할 때 유용하다.

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

//any로 다루고 있기 때문에 index 1번째 요소가 boolean 타입이지만 number 타입으로 재할당할 수 있습니다. 
list[1] = 100;

TypeScript 함수

//named function
function add(x: number, y: number):number {
	return x + y;
}

//arrow function
let add = (x: number, y: number): number => {
	return x + y;
}

만일 함수에 리턴값이 없다면, void를 사용하여 작성할 수 있다.

let printAnswer = (): void => {
	console.log("YES");
}

TypeScript는 JavaScript와 달리 매개변수의 개수에 맞춰 전달인자를 전달한다.

let greeting = (firstName: string, lastName: string): string => {
	return `hello, ${firstName} ${lastName}`;
}

//에러가 납니다.
greeting('coding');

//정상적으로 작동합니다.
greeting('coding', 'kim');

//너무 많은 매개변수를 보내 에러가 납니다.
greeting('coding', 'kim', 'hacker')

전달인자를 전달하지 않거나, undefined를 전달했을 때 할당될 매개변수의 값을 정해놓을 수도 있습니다. 이는 JavaScript에서의 default parameter와 같은 동작을 한다.

let greeting = (firstName: string, lastName="kim"): string => {
	return `hello, ${firstName} ${lastName}`;
}

//정상적으로 작동합니다. 
greeting('coding');

//정상적으로 작동합니다.
greeting('coding', undefined);

//너무 많은 매개변수를 보내 에러가 납니다.
greeting('coding', 'kim', 'hacker');

선택적 매개변수를 원한다면 매개변수의 이름 끝에 ?를 붙임으로써 해결할 수도 있다.

let greeting = (firstName: string, lastName?: string): string => {
	return `hello, ${firstName} ${lastName}`;
}

//정상적으로 작동합니다.
greeting('coding');

//정상적으로 작동합니다.
greeting('coding', 'kim');

//너무 많은 매개변수를 보내 에러가 납니다.
greeting('coding', 'kim', 'hacker');

그러나 이때는 greating('coding')과 같이 전달인자를 하나만 전달했기 때문에, 뒤의 매개변수는 undefined로 반환된다.

TypeScript 연산자 활용 타입(유니온과 인터섹션)

1. 유니온(Union) 타입 - | 연산자를 이용하며, 자바스크립트의 || (OR) 연산자와 같이 “A이거나 B이다”라는 의미의 타입이다.

function printValue(value: number|string): void {
  if (typeof value === "number") {
    console.log(`The value is a number: ${value}`);
  } else {
    console.log(`The value is a string: ${value}`);
  }
}

printValue(10); // The value is a number: 10
printValue("hello"); // The value is a string: hello

1-2. 유니온(Union) 타입의 장점

유니온 타입을 사용하면 타입을 추론할 수 있기 때문에, 타입에 관련된 API를 쉽게 자동완성으로 얻어낼 수 있다.

1-3. 유니온(Union) 타입 사용 시 유의할 점

유니온에 있는 모든 타입에 공통인 멤버들에만 접근할 수 있기 때문에 유의해야한다.

interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
  age: number;
}

인터페이스를 사용하여 Developer와 Person을 정의한다.

function askSomeone(someone: Developer | Person) {
	console.log(someone.name);
}

그러나 실질적으로 askSomenone 함수 내부에서는 Developer와 Person이 갖고 있는 공통 프로퍼티인 name에만 접근할 수 있다. 공통되고 보장된 프로퍼티만 제공해야 하기 때문이다. 나머지 프로퍼티에도 접근하고 싶다면 타입 가드를 사용해야 한다.

타입 가드(Type Guard)란? TypeScript에서 타입을 보호하기 위해 사용되는 기능 중 하나이다. 타입 가드는 특정 코드 블록에서 타입의 범위를 제한해 해당 코드 블록 안에서 타입 안정성을 보장해 준다.

function askSomeone(someone: Developer | Person) {
  // in 연산자 : 타입스크립트에서 객체의 속성이 존재하는지를 체크하는 연산자
  // in 연산자는 객체의 속성 이름과 함께 사용하여 해당 속성이 객체 내에 존재하는지 여부를 검사
  if ('skill' in someone) {
    console.log(someone.skill);
  }

  if ('age' in someone) {
    console.log(someone.age);
  }
}

n 연산자는 객체의 프로퍼티 이름과 함께 사용되며, 해당 프로퍼티가 객체 내에 존재하는지 여부를 검사한다.

인터섹션(Intersection) 타입

인터섹션(Intersection)은 둘 이상의 타입을 결합하여 새로운 타입을 만드는 방법입니다. & 연산자를 사용

let value: string & number & boolean;

value 변수는 string, number, boolean 타입을 전부 받을 수 있습니다.인터섹션으로 타입을 연결해 하나의 단일 타입으로 표현할 수 있기 때문에, 타입 가드가 필요하지 않다.

interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
  age: number;
}

function askSomeone(someone: Developer & Person) {
  console.log(someone.age);
	console.log(someone.name);
	console.log(someone.skill);
}

인터섹션 타입을 사용하여 Developer와 Person을 하나의 타입으로 묶었습니다. 따라서 askSomeone 함수 내에선 정의된 프로퍼티에 전부 접근할 수 있습니다.

그러나 인터섹션 타입은 타입 가드는 필요 없는 반면 Developer와 Person이라는 새로운 합집합을 만들어 내는 것이기 때문에, 전달인자를 전달할 때 모든 프로퍼티를 전부 보내줘야만 합니다. 반대로 유니온 타입은 타입 가드를 해줘야 하지만 전달인자를 전달할 때 선택지가 생기게 됩니다.

interface Developer {
  name: string;
  skill: string;
}

interface Person {
  name: string;
  age: number;
}

function askSomeone(someone: Developer | Person) {
	//이런 식으로 프로퍼티에 접근할 수 있습니다.
  if ('skill' in someone) {
    console.log(someone.skill);
  }

  if ('age' in someone) {
    console.log(someone.age);
  }
}

//유니온 타입은 전달인자를 전달할 때 선택지가 생깁니다.
askSomeone({name: '김코딩', skill: '웹 개발'});
askSomeone({name: '김코딩', age: 20});

function askSomeone2(someone: Developer & Person) {
	//타입 가드를 사용하지 않아도 모든 프로퍼티에 접근할 수 있습니다.
  console.log(someone.age);
	console.log(someone.name);
	console.log(someone.skill);
}

//그러나 인터섹션 타입으로 결합하게 된다면 전달인자를 전달할 때 선택지가 없습니다.
askSomeone2({name: '김코딩', skill: '웹 개발', age:20});
profile
Explain Like I'm 5

0개의 댓글