https://github.com/ssi02014/typescript-todolist
π TypeScript 곡λΆνλ©΄μ Classννλ‘ λ§λ€μ΄λ³΄λ ToDoList
https://github.com/ssi02014/typescript-todolist
Last synced: 8 months ago
JSON representation
π TypeScript 곡λΆνλ©΄μ Classννλ‘ λ§λ€μ΄λ³΄λ ToDoList
- Host: GitHub
- URL: https://github.com/ssi02014/typescript-todolist
- Owner: ssi02014
- Created: 2021-06-08T14:45:33.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-06-22T12:40:14.000Z (over 4 years ago)
- Last Synced: 2024-12-30T06:44:48.395Z (9 months ago)
- Language: TypeScript
- Homepage:
- Size: 128 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# π» TypeScript-ToDoList
νμ μ€ν¬λ¦½νΈλ‘ λ§λ€μ΄λ³΄λ ToDoList π
## π νλ‘μ νΈ μμ μ μ ν κ³Όμ
### π 1. νμ μ€ν¬λ¦½νΈ μ€μΉ
```
node install -g typescript
npm install -g ts-node
```
### π 2. tsconfig.json μμ± λ° μ€μ
```
//tsconfig.json μμ±
tsc --init
```
- tsconfig.json μ€μ
```json
{
"compilerOptions": {
/* Basic Options */
"target": "es5",
"module": "commonjs",
"outDir": "./build", //λΉλ λ μ΄ν μλ°μ€ν¬λ¦½νΈ νμΌμ΄ μ μ₯ λ μ₯μ
"rootDir": "./src", //νμ μ€ν¬λ¦½νΈ μμ€μ½λκ° μλ μ μ₯μ/* Strict Type-Checking Options */
"strict": true,/* Module Resolution Options */
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}```
### π 3. package.json μμ± λ° μ€μ
```
//package.json μμ±
npm init -y
```
- package.json μ€μ
```json
{
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc -w",
"start:run": "nodemon build/index.js",
"start": "concurrently npm:start:*"
},
...
}
```### π nodemon, concurrently μ€μΉ
```
npm install nodemon concurrently
```
- concurrentlyλ λμμ μ¬λ¬ λͺ λ Ήμ΄λ₯Ό μ€ννκΈ° μν΄ μ¬μ©λλ€.
- nodemon: μ€μκ°μΌλ‘ μμ μ¬νμ λ°μν΄μ€λ€.
## π¨βπ» TodoItem: JavaScript vs TypeScript
### π JavaScript
```js
class TodoItem {
constructor(id, task, complete) {
this.id = id;
this.task = task;
this.complete = complete;
}printDetails() {
console.log(
`${this.id} \t ${this.task} \t ${this.complete ? "(complete)" : ""}`
);
}
}
```
### π TypeScript
- νμ μ€ν¬λ¦½νΈμμλ νμ μ μ§μ ν΄μ£Όλκ±° μ΄μΈμ `μ κ·Ό μ§μ μ(private, public, protected)` λ±μ μ§μ ν μ μλ€.
- μμ±μ(contructor)μμμ `μ κ·Ό μ§μ μ`λ₯Ό μ§μ νλ©΄ λ°λ‘ νλ‘νΌν° μ μν νμ μμ΄ νλ‘νΌν°λ‘ μ μλλ€.
- ν¨μμ λ¦¬ν΄ κ°μ΄ μμΌλ©΄ λ°ν κ° νμ μ `void`λ‘ μ§μ ν΄μΌ νλ€.
```ts
class TodoItem {
constructor(public id: number, public task: string, public complete: boolean) {
this.id = id;
this.task = task;
this.complete = complete;
}printDetails(): void {
console.log(
`${this.id} \t ${this.task} \t ${this.complete ? "(complete)" : ""}`
);
}
}export default TodoItem;
```
## π¨βπ» TodoCollection
### π getTodoById λ©μλ
- ν¨μ λ°ν κ°μ λν νμ μ `TodoItem | undefined`μ΄λ° μμΌλ‘ μ§μ νλ©΄ λ°ν κ°μ νμ μ΄ TodoItem λλ undefinedλΌλ μλ―Έ
```ts
import TodoItem from "./TodoItem";class TodoCollection {
...
getTodoById(id: number): TodoItem | undefined {
return this.todoItems.find((item) => item.id === id);
}
...
}export default TodoCollection;
```
### πββοΈ Type Annotations - Inference Around Functions
- ν¨μμ νλΌλ―Έν°λ₯Ό μ μν λ κ° νλΌλ―Έν°μ νμ μ μ§μ νμ§ μμΌλ©΄ `any` νμ μ νλΌλ―Έν°κ° μ§μ λλ€.
- ν¨μμ νλΌλ―Έν°μ νμ μ μ§μ νμ§ μμΌλ©΄ μΌλ° λ³μμ λ§μ°¬κ°μ§λ‘ μ묡μ μΈ any νμ μ μ μ©μΌλ‘ κ²½κ³ μ¬νμ΄λ€.
- ν¨μμ λ°ν κ°μ λν νμ μ return μ€νλ¬Έμ λ°λΌ `νμ μΆλ‘ (Type Inference)`μ΄ μ μ© λλ€.
- λ°ν κ°μ κ²½μ° retrun ꡬ문μΌλ‘ `λͺ μμ μΈ νμ μ μ μΆ`κ° κ°λ₯νλ€.
- ν¨μμ λ°ν κ°μ΄ μμ κ²½μ° `void` νμ μ λ°νμ μ μνλ€.
- ν¨μμ λ°ν κ°μΌλ‘ μ μ κ°λ₯ν `never` νμ μ μ λ λ°μνμ§ μλ κ°μ νμ μ λνλΈλ€. μ½κ² λ§νλ©΄ λ°νμ μνλ€λ μλ―Έ
- `void` νμ μ λ³μλ‘ μ¬μ© λ κ²½μ° `undefined`, `null` κ°λ§ λμ (assign)μ΄ κ°λ₯νλ€.
- `never`νμ μ μ΄λ€ λ³μμ λ³μμλ λμ λ μ μμ§λ§, never νμ μλ μ΄λ€ νμ μ κ°λ λμ λ μ μλ€.
### πββοΈ Type Annotations - Tuple
- ννμ μ΄μ©νλ©΄ λ°°μ΄μ μμ μμ κ° μμμ λν νμ μ μ§μ ν μ μλ€.
- ννμ μ ν΄μ§ κΈΈμμ λ§μ§ μμΌλ©΄ μλ¬κ° λ°μ. νμ§λ§ `push()`λ ννμ κ·μΉμ 무μν¨.
- μλ‘ λ€λ₯Έ νμ μ μμλ₯Ό κ°λ λ°°μ΄μ μμμ μκ΄μμ΄ λ°μ΄ν°λ₯Ό λ£μ μ μμ§λ§, λ°λ©΄ ννμ μ ν΄μ§ μμμ λ§κ² λ£μ΄μΌ ν¨
- νν νμ μ λ°°μ΄λ³΄λ€ μ μ₯λλ μμμ μμμ μμ μ μ½μ λκ³ μ ν λ μ¬μ©
```ts
const tuples: [string, number] = ['Jeon', 27]; //νν
const arr: (string | number)[] = ['Jeon', 27, 'MinJae', 26]; //λ°°μ΄tuples[0] = 'Park' // OK
tuples[0] = 50 // Error: Type '50' is not assignable to type 'string'.ts(2322)tuples[1] = 50 // OK
tuples.push(100);
console.log(tuples); // ['Park', 50, 100]
```
### πββοΈ Generics
- μ¬μ¬μ© κ°λ₯ν ν΄λμ€, ν¨μλ₯Ό λ§λ€κΈ° μν΄ λ€μν νμ μμ μ¬μ© κ°λ₯ νλλ‘ νλ κ²μ΄ `μ λ€λ¦`μ΄λ€.
- μ λ€λ¦μ μ΄μ©νλ©΄ λͺ¨λ νμ μ κ°μ²΄λ₯Ό λ€λ£¨λ©΄μ κ°μ²΄ νμ μ 무결μ±μ μ μ§ν μ μλ€.
- μ λ€λ¦μ ν΅ν΄ ν΄λμ€λ ν¨μ λ΄λΆμμ μ¬μ©λλ νΉμ λ°μ΄ν°μ νμ μ μΈλΆμμ μ§μ νλ€.
- μ λ€λ¦μ΄ μ μ©λ λμ(ν΄λμ€, ν¨μ, μΈν°νμ΄μ€)μ μ μΈ μμ μ΄ μλ μμ± μμ μ μ¬μ©νλ νμ μ κ²°μ νλ€.```ts
class Box {
constructor(private fruit: T) {}
getFruit(): T {
return this.fruit;
}
}
```
- μ μ½λμμ ``μ μ μ΄ μ λ€λ¦μ μ μ© μ΄λ₯Ό νμ νλΌλ―Έν°λΌκ³ νλ€.
- Tλ§κ³ μ΄λ ν μνλ²³μ μ¬μ©ν΄λ μκ΄μ μμ§λ§ κ΄μ©μ μΌλ‘ Tλ₯Ό μ¬μ©
```ts
const box: Box = new Box(new Orange(5));
```
- μμ μ½λλ₯Ό 보면 boxλ₯Ό μ μνλ©΄μ boxμ νμ μΌλ‘ Boxμ νμ μ μ λ€λ¦μΌλ‘ ``λ₯Ό μ§μ ν¨ μ€μ μΈμ€ν΄μ€ν νλ©΄μ Orange κ°μ²΄λ₯Ό μμ±ν΄μ λ£μ
```ts
class Box {
constructor(private fruit: Orange) {}
getFruit(): Orange {
return this.fruit;
}
}
```
- κ²°κ³Όμ μΌλ‘ TλΌκ³ μ§μ λ νμ λ€μ λͺ¨λ Orange νμ μ΄ λλ€.
### πββοΈ type alias
- μλ‘μ΄ νμ μ μ μνλ λ°©λ²μ type aliasμ interfaceλ₯Ό μ μνλ λ κ°μ§ λ°©μμ΄ μλ€.
- type aliasλ₯Ό μ΄μ©νλ©΄ κ°μ²΄, 곡μ©μ²΄(Union), νν(Tuple), κΈ°λ³Έ νμ μ νμ μ λ³μΉμ μμ±ν μ μλ€.
- type aliasλ μ λ€λ¦μ μ¬μ©μ΄ κ°λ₯νλ©°, μ€μ€λ‘ μ°Έμ‘°νλ κ²λ κ°λ₯νλ€.
```ts
type MyNumber = number;
const n: MyNumber = 10;type Container = { value: T };
type User = { name: string, age: number };
const testUser: User = { name:"Kim", age:20 };
//=== const testUser: { name: string, age: number } = { ... }
```
## π¨βπ» TodoConsole
### πββοΈ inquirer λΌμ΄λΈλ¬λ¦¬ μ€μΉ
- inquirer: Interactive user promptλ₯Ό ꡬνμ μν λΌμ΄λΈλ¬λ¦¬λ‘ 루λΉ, νμ΄μ¬, μλ°μ€ν¬λ¦½νΈ λ± μ¬λ¬κ°μ§ μΈμ΄λ₯Ό μ§μνκ³ μΌλ°μ μΈ μ¬μ©μ μ λ ₯ ꡬν, 체ν¬λ°μ€, λΌλμ€ λ²νΌ λ± κ΅¬νμ΄ νΈλ¦¬νλ€.
- λ¨, TypeScriptμμλ @types/inquirerμ μΆκ°μ μΌλ‘ μ€μΉν΄μΌ νλ€.
```
npm i inquirer @types/inquirer
```
### πββοΈ inquirer μ¬μ© μμ
- src/model/TodoConsole.ts
```ts
import * as inquirer from 'inquirer';class TodoConsole {
...
promptUser(): void {
console.clear();
this.displayTodoList();inquirer.prompt({
type: 'list',
name: 'command',
message: 'Choose option',
choices: Object.values(Commands),
}).then((answers) => {
if(answers['command'] !== Commands.Quit) {
this.promptUser();
}
});
}
}export default TodoConsole;
```
- src/model/Command.ts
```ts
export enum Commands {
Quit = 'Quit',
Add = 'Add',
}
```
- μ£Όμν μ μ nodemon, concurrentlyμ μ¬μ©ν΄μ npm startλ₯Ό νλ©΄ μ½κ°μ μ€λ₯κ° μμ
- node build/index.js λ‘ λΉλ νκ³ μ€νν΄μΌ λλ€.
### πββοΈ enum
- μ΄κ±°ν(enum) νμ μ `μμ`λ€μ κ΄λ¦¬νκΈ° μν κ°μ²΄λ‘ μμμ μ§ν©μ μ μνλ€.
- μΌλ° κ°μ²΄λ μμ±μ λ³κ²½μ νμ©νμ§λ§ μ΄κ±°νμ μμ±μ λ³κ²½μ νμ©νμ§ μλλ€.
- μ΄κ±°νμ μμ±μ κΈ°λ³Έμ μΌλ‘ `μ«μ`, `λ¬Έμμ΄`λ§ νμ©νλ€.
- μ΄κ±°νμ μ΄μ©νλ©΄ μμμ μλ₯Ό μ νν μ μμΌλ©° μ½λμ κ°λ μ±μ λμΌ μ μλ€.
```ts
const korean = 'ko';
const english = 'en';
const japanese = 'ja';type LanguageCode = 'ko' | 'en' | 'ja';
const code: LanguageCode = korean;
```
- μ μ½λλ₯Ό μμ νλ©΄
```ts
enum LanguageCode {
korean = 'ko',
english = 'en',
japanese = 'ja',
}const code: LanguageCode = LanguageCode.korean;
```
## π¨βπ» Union Type/Type Guard
### πββοΈ Union Type
- TypeScriptλ νμ λ€μ μ‘°ν©μ ν΅ν΄ μλ‘μ΄ νμ μ μ μν μ μμΌλ©° Union Typeλ κ·Έμ€ νλμ΄λ€.
- Union Typeμ νμ μ μΈμ νλ μ΄μμ νμ μ μ§μ νκ³ ν΄λΉ νμ μ€μ νλμΌ μ μμμ λνλΈλ€.
- Union Typeμ μ μλ `|` μ°μ°μλ₯Ό μ΄μ©ν΄ μ μνλ€.
- Union Typeμ λ©€λ² μ¬μ©μ μ μλ λͺ¨λ νμ μ 곡ν΅μ μΈ λ©€λ²λ€λ§ μ¬μ©ν μ μλ€.
### πββοΈ Type Guard
- Type Guardλ νΉμ μμ(λΈλ‘) μμμ ν΄λΉ λ³μμ νμ μ νμ μμΌμ£Όλ κΈ°λ₯μ΄λ€.
- Union Typeμ μ μλ κ° νμ μ΄ κ°λ κ³ μ λ©€λ²λ μ¬μ©ν μ μλ€.
- νΉμ μμμμ κ° νμ μ΄ κ°λ κ³ μ λ©€λ²μ λν μ¬μ©μ Type Guardλ₯Ό μ΄μ©ν©λλ€.
- Type Guardλ μ¬μ©μκ° μ μ νκ±°λ `number`, `string`, `boolean`, `Symbol`μ κ²½μ° `typeof` μ°μ°μλ₯Ό μ΄μ©νλ€.
```ts
let collection: number[] | string;
collection = 'TypeScript';collection.split(''); //μ¬μ©ν μ μμ. μ? μ«μλ°°μ΄μ splitμ΄λΌλ λ©μλλ₯Ό κ°κ³ μκΈ° μκΈ° λλ¬Έ
//Type Guard
if (typeof collection === 'string') {
//collectionμ΄ stringμ΄λΌλκ² trueλΌλ©΄ μ΄ λΈλ μμμλ split λ©μλλ₯Ό μ¬μ©ν μ μλ€.
collection.split('');
}
```