이제 곧 프로젝트를 시작하는데 Typescript를 활용한다고 한다. 그래서 노마드코더님의 타입스크립트 무료 강의를 듣고 개념을 정리해보았다.
강의 링크
https://nomadcoders.co/typescript-for-beginners
(타입스크립트를 입문하는 분들에게 추천한다!)
Typescript 특징
- TypeScript는 JavaScript에 추가적인 구문을 통해 단단한 통합을 제공하며 초기 오류를 감지할 수 있다.
- TypeScript 코드는 JavaScript로 변환되어 브라우저, Node.js, 앱 등에서 실행될 수 있다.
- JavaScript를 이해하며 타입 추론을 사용하여 추가 코드 없이 도구를 제공한다.
Type
명시적 정의와 변수 생성
let a: boolean = "x"; // 🚫 boolean 타입에 string 타입 할당 불가 알림
let b = "hello"; // b가 string 타입으로 추론
b = 1; // 🚫 string 타입에 number 타입 할당 불가 알림
기본 타입 예시: 배열, 숫자, 문자열, optional
const player: {
name: string;
age?: number;
} = {
name: "nick",
};
이 때 age는 옆에 ?가 붙어있기 때문에 optional parameter이다. age 속성은 있을 수도 있고 없을 수도 있다.
Alias(별칭) 타입 활용
type Player = {
name: string;
age?: number;
};
const player: Player = {
name: "nick",
};
정의된 타입 Player를 이용하여 player라는 객체를 생성했다.
이렇게 하면 player 객체는 Player 타입을 따르게 된다.
타입 별칭은 코드를 간결하게 만들어주고, 타입을 재사용하기 쉽게 해주는 유용한 기능이다.
함수 활용 예시 코드
type Player = {
name: string;
age?: number;
};
// (name: string)은 함수의 매개변수 목록이다.
// : 뒤에 오는 부분은 함수가 반환하는 값의 타입을 나타낸다.
// -> Player 타입을 반환한다는 뜻
function playerMaker1(name: string): Player {
return { name };
}
// 화살표 함수로도 생성이 가능하다.
// { name } -> name : name과 같은 뜻
const playerMaker2 = (name: string): Player => ({ name });
const nick = playerMaker1("nick");
nick.age = 12;
readonly는 한 번 값을 할당하면 그 값을 변경할 수 없도록 만든다.
type Player = {
readonly name: string;
age?: number;
};
const playerMaker = (name: string): Player => ({ name });
const nico = playerMaker("nick");
// 🚫 nico.name = "aa";
Tuple 예시
const player: [string, number, boolean] = ["nick", 1, true];
Undefined, Null, Any, Unknown, Void, Never 등 다양한 타입을 활용할 수 있다.
Call Signature
Call Signature를 통해 함수의 형태를 정의하면 해당 형태를 가지는 함수를 만들 수 있다.
type Add = {
(a: number, b: number): number;
};
const add: Add = (a, b) => a + b;
Function Overloading
Function Overloading은 동일한 함수 이름을 가지면서 매개변수의 개수나 타입을 다르게 정의하여 여러 형태의 호출을 지원하는 개념이다.
여러 형태의 호출에 대응하기 위해 함수 시그니처를 정의하며, 이러한 시그니처들은 모두 동일한 함수 몸체를 가리킨다.
type Add2 = {
(a: number, b: number): number;
(a: number, b: number, c: number): number;
};
const add2: Add2 = (a, b, c) => {
if (c) return a + b + c;
return a + b;
};
- c가 주어지면, 세 개의 숫자를 받아 합을 반환한다.
- c가 주어지지 않으면, 두 개의 숫자를 받아 합을 반환한다.
Generics
선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있도록 하는 기법
단일 타입이 아닌 다양한 타입에서 작동할 수 있는 컴포넌트를 생성할 수 있다.
function identity<Type>(arg: Type): Type {
return arg;
}
- <Type>: 제네릭 타입 매개변수를 정의하는 부분이다. 여기서 **Type**은 임의의 식별자로, 실제로 사용되는 이름은 중요하지 않다. <T>, <U>, <A> 등의 임의의 이름을 사용할 수 있다.
- (arg: Type): 함수의 매개변수 **arg**는 **Type**으로 지정된 타입을 받습니다. 즉, 이 함수는 어떤 타입의 값이든 받을 수 있다.
- : Type: 함수의 반환 타입
Abstract Class
- 다른 클래스가 상속받을 수 있는 클래스
- 직접 새로운 인스턴스 생성 X
abstract class User {
constructor(
private firstName: string,
private lastName: string,
public nickname: string
) {}
abstract getNickName(): void;
}
private를 사용하면 상속받은 클래스 안에서 마저도 this 사용해 접근 불가능
그래서 protected를 사용하면 상속받은 클래스 안에서 this 사용해 접근 가능
물론 protected로 지정된 것들은 외부에서 사용이 불가능
추상클래스 안에 메소드는 적어서는 안되고 call signature만 적어야 함
추상클래스 안의 메소드는 결국 구현이 되지 않는다고 나옴
Interface
Interface에 비해 Type은 다양한 목적으로 활용될 수 있다.
그에 비해 Interface는 오로지 객체의 형태를 Typescript에게 설명해주기 위한 용도로만 사용된다.
(그리고 Property들을 축적시킬 수 있다.)
→ 클래스나 오브젝트의 모양을 정의하고 싶으면 Interface를 사용하고, 다른 모든 경우에는 Type을 사용하자.
예시
// 간단한 인터페이스 정의
interface Person {
name: string;
age: number;
isStudent?: boolean; // 선택적 속성
}
// Person 인터페이스를 사용한 객체
const student: Person = {
name: "John",
age: 20,
isStudent: true,
};
const teacher: Person = {
name: "Jane",
age: 35,
// isStudent 속성은 선택적이므로 생략 가능
};
// 함수 시그니처에 인터페이스 활용
interface Greet {
(name: string): string;
}
const greetPerson: Greet = (name) => `Hello, ${name}!`;
console.log(greetPerson("Alice")); // 출력: Hello, Alice!
TypeScript를 쓰려면
‘npm init -y’: package.json 생성
‘npm i -D typescript’ : typescript 설치
‘tsc —init’: tsconfig.json 생성
tsconfig.json 설정
target: ECMAScript 버전 설정
lib
- 타입스크립트에게 어떤 API를 사용하고 어떤 환경에서 코드를 실행하는 지를 지정할 수 있다.
- 프로그램이 브라우저에서 실행되면 lib에 "DOM" 유형 정의를 할 수 있다.(window, document 사용 가능)
- ex) "lib": ["ES6","DOM"]
Javascript로 만들어진 패키지를 설치했을 때 Typescript에 그 패키지의 타입을 정의하는 방법
우리가 타입스크립트에게 패키지가 어떻게 생겼는지, 어떤 함수랑 다른 것들이 있는지 설명해야한다. → d.ts(declaration file)에 설명을 추가한다.
tsconfig.json에서 "strict": true를 통해 strict mode로 해주면, Declaration Files가 없는 경우에 대해서도 에러를 띄워준다.
@ts-check
JavaScript 파일에서 오류를 활성화하려면 @ts-check를 .js 파일의 첫 번째 줄에 추가하여 TypeScript가 오류를 발생시키도록 할 수 있다. TypeScript는 여러 오류를 제공한다.
예시
// @ts-check
/**
* Initializes the project
* @param {object} config
* @param {boolean} config.debug
* @param {string} config.url
* @returns boolean
*/
export function init(config) {
return true;
}
/**
* Exits the program
* @param {number} code
* @returns number
*/
export function exit(code) {
return code + 1;
}
Definitelytyped와 @types/node
- DefinitelyTyped는 TypeScript로 작성된 자바스크립트 라이브러리 및 프레임워크의 타입 정의 파일(TypeScript Definition)을 모아놓은 온라인 리포지토리
예를 들어, Node.js의 express 라이브러리에 대한 타입 정의를 사용하려면 다음과 같이 설치할 수 있다.
설치 명령어
npm install --save-dev @types/express
이러한 타입 정의를 사용하면 TypeScript 코드에서 express 라이브러리를 사용할 때 코드 완성 및 타입 검사의 혜택을 받을 수 있다.
ts-node
ts-node는 TypeScript 코드를 직접 실행하고 실행 결과를 보여주는 도구
일반적으로 Node.js는 JavaScript 코드만 실행할 수 있지만, TypeScript는 JavaScript를 기반으로 하는 언어이기 때문에 TypeScript 코드를 JavaScript로 컴파일한 후에 Node.js에서 실행해야 한다.
ts-node를 사용하면 TypeScript 소스 코드를 직접 실행할 수 있다.
→ TypeScript 파일(*.ts)을 빌드하지 않고도 Node.js에서 바로 실행할 수 있다.
ts-node를 사용하기 위해서는 먼저 해당 패키지를 전역 또는 로컬로 설치해야 한다.
설치 명령어
npm install -D -ts-node
설치가 완료되면 터미널에서 다음과 같이 TypeScript 파일을 실행할 수 있다.
ts-node your-file.ts
nodemon
nodemon은 Node.js 애플리케이션을 개발할 때 사용되는 도구로, 코드 변경 사항을 감지하고 자동으로 서버를 재시작하는 기능을 제공한다.
→ 코드를 수정하고 저장할 때마다 수동으로 서버를 다시 시작할 필요가 없어진다.
설치 명령어
npm install -D nodemon
ts-node와 nodemon을 같이 쓰면?
package.json에 아래와 같이 추가했다.
"scripts": {
"dev": "nodemon --exec ts-node src/index.ts",
},
그리고 ‘npm run dev’ 명령어를 입력하면 앞으로는 TypeScript 파일의 변경을 할 때마다 변경을 감지하고 자동으로 다시 컴파일하며 서버를 다시 시작한다.
'Frontend > Typescript' 카테고리의 다른 글
[Vite + TS] Vite에서 svg 파일을 못 읽을 때(@svgr/rollup 사용) (0) | 2024.03.02 |
---|